我会尽量使这个变得简单(这比我所见的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
对用户界面执行任何操作,我只是想让它告诉我,无论是真还是假。
我不想将它与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;
}
}
答案 0 :(得分:2)
首先,您不应该在主线程上执行您的请求。此外,在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);