安卓Okhttp异步调用

13

我希望使用Okhttp库通过API将我的Android应用连接到服务器。

当我在按钮上点击时进行API调用,但是我收到了android.os.NetworkOnMainThreadException的错误提示。我知道这是因为我试图在主线程上进行网络调用,但我也很难在Android上找到一个干净的解决方案来使这段代码使用另一个线程(异步调用)。

@Override
public void onClick(View v) {
    switch (v.getId()){
        //if login button is clicked
        case R.id.btLogin:
            try {
                String getResponse = doGetRequest("http://myurl/api/");
            } catch (IOException e) {
                e.printStackTrace();
            }
            break;
    }
}

String doGetRequest(String url) throws IOException{
    Request request = new Request.Builder()
            .url(url)
            .build();

    Response response = client.newCall(request).execute();
    return response.body().string();

}
上面是我的代码,并且异常被抛出在这一行。
Response response = client.newCall(request).execute();

我也看到Okhttp支持异步请求,但是我在Android中找不到一个干净的解决方案,因为大多数人似乎都使用一个使用AsyncTask<>的新类?

1个回答

37

要发送异步请求,请使用以下代码:

void doGetRequest(String url) throws IOException{
    Request request = new Request.Builder()
            .url(url)
            .build();

    client.newCall(request)
            .enqueue(new Callback() {
                @Override
                public void onFailure(final Call call, IOException e) {
                    // Error

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            // For the example, you can show an error dialog or a toast
                            // on the main UI thread
                        }
                    });
                }

                @Override
                public void onResponse(Call call, final Response response) throws IOException {
                    String res = response.body().string();

                    // Do something with the response
                }
            });
}

& 这样调用:

case R.id.btLogin:
    try {
        doGetRequest("http://myurl/api/");
    } catch (IOException e) {
        e.printStackTrace();
    }
    break;

2
try {...} catch (IOException e) {...} 和当然的 doGetRequest(String url) throws IOException{ 中是没有必要的。 - Vlad
@V.Kalyuzhnyu,try...catch将处理由doGetRequestIOException抛出的错误。 - kirtan403
1
如果响应体很大且不能立即使用,则String res = response.body().string();将会阻塞(因此最好在单独的线程池中进行阻塞操作)。另外,最好将其包装在try (Response res = response)中以确保响应已关闭,例如,如果其中没有响应体。 - silmeth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接