如何在Android和WAIT中执行Java HTTP GET调用以获得响应?

时间:2018-02-23 00:40:47

标签: java android http

我会尽量使这个变得简单(这比我所见的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;
    }
}

1 个答案:

答案 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);