我将尝试使其尽可能简单(这超出了我所见过的 Java HTTP 设置的范围)。
我的 Activity 中有一个决策树(伪):
private void okOnClick(View v){
if(HttpService.isCredentialValid()){
//wait to do something
} else {
//wait to do something else
}
}
然后我有一个 HttpService:
public class HttpService {
public static boolean isCredentialValid(){
//GET `http://my_server:8080/is-valid?someParam=123`
//the endpoint will return a 200 or 500
}
}
我不希望 isCredentialValid
对 UI 执行任何操作,我只是希望它告诉我,是真是假。
我不想将其与 button.setText()
或任何其他内容紧密耦合,我只想要一个简单的合约 response.code == 200
在几乎所有语言中,这都不是那么困难。有人可以帮我纠正一下吗?
...对于任何敌意的声音感到抱歉。这是我使用过的几乎所有代码库中最基本的机制之一。我只发现异步模式无法向方法调用者返回实质性内容。或者我发现危及主线程的方法无法捕获错误(例如,当没有连接时)。
<小时/>到目前为止,我已经尝试过类似下面的方法(调整代码以简化)。我允许它在主线程上操作,因为我确实希望它同步阻塞。然而,没有办法捕捉到互联网连接不良或远程服务器没有响应的情况:
public static boolean isCredentialValid(){
String url = "http://my_server:8080?param=123";
StrictMode.ThreadPolicy policy = new
StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
try {
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(1, TimeUnit.SECONDS)
.writeTimeout(1, TimeUnit.SECONDS)
.readTimeout(1, TimeUnit.SECONDS)
.build();
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.code() == 200;
} catch(Exception e){
//
//THIS DOES NOT GET HIT WHEN THERE
//IS A BAD CONNECTION OR REMOTE SERVER FAILS TO RESPOND
//the app just hangs then quits
//
Log.d("ERROR:", e.toString());
return false;
}
}
最佳答案
首先,您不应该在主线程上执行您的请求。此外,在 Android 上,HTTP 请求是异步执行的,如果您需要同步执行它们作为方法的返回,那么这是一种非常糟糕的做法,并且会产生代码味道。实现您想要实现的目标的正确方法是使用回调模式。您的方法不应返回任何内容,而应调用回调,该回调应作为其参数之一接收。如果您仍然非常需要同步执行操作,因为您不知道如何处理异步调用,或者您的架构不允许这样做,那么使用 CountDownLatch 怎么样?对不起,我的 Kotlin,但基本上它的工作原理是这样的:
val countDownLatch = CountDownLatch(1)
// Execute your request
countDownLatch.countDown()
try {
countDownLatch.await(30, TimeUnit.SECONDS) // Give it a 30 seconds timeout
// return the response code here.
} catch (ex: InterruptedException) {
// Catch the timeout exception
}
无论如何,您可能应该重新考虑从该方法实际返回的必要性,而不是使用回调,我建议的并不完全是最佳实践。
PS:下面的代码确实是一个坏主意。基本上,您所做的就是强制 Android 在主线程上允许 HTTP 请求,这将完全阻止应用程序的 UI。
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
关于java - 如何在 Android 中执行 Java HTTP GET 调用并等待响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48939474/