image
在上兩篇文章中介紹了OkHttp同步請求以及同步請求的源碼分析,其中也提到了OkHttp的同步請求和異步請求的前三步是一模一樣的流程。
這前三步是:
- 第一步 創(chuàng)建 OkHttpClient 對象(OkHttpClient代表是客服端類)
- 第二步 同樣以Builder的模式創(chuàng)建了 Request 對象
- 第二步 創(chuàng)建 Call 對象(將創(chuàng)建的request封裝成了Call對象)
如果不清楚明細可以查看上兩篇文章OkHttp同步請求和OkHttp同步請求 源碼分析的前三步分析。
前三步在前面的文章已分析過了,那直接看異步請求的第四步:
通過 call 對象調(diào)用enqueue(Callback responseCallback)方法發(fā)送異步請求
這也是OkHttp同步異步請求的分水嶺,我們直接看以下代碼:
//第一步 創(chuàng)建OkHttpClient對象
OkHttpClient client = new OkHttpClient.Builder().build();
//第二步 創(chuàng)建Request對象
Request request = new Request.Builder().url("https://gank.io/api/xiandu/categories").build();
//第三步 創(chuàng)建Call對象(Call其實是一個接口,具體實現(xiàn)還是RealCall類中)
Call call = client.newCall(request);
//第四步 call對象調(diào)用enqueue()方法,通過Callback()回調(diào)拿到響應(yīng)體Response
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//異步請求失敗之后的回調(diào)
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//異步請求成功之后的回調(diào)
}
});
在上面的代碼我們知道了OkHttp異步請求是 call 對象調(diào)用的 enqueue() 方法
這里需要注意的是當調(diào)用的 enqueue() 方法的時候,它是回去開啟一個新的工作線程,然后OkHttp會讓這個網(wǎng)絡(luò)請求在這個工作線程中去執(zhí)行,也就是子線程中去執(zhí)行。
然后通過 Callback()回調(diào)了請求的結(jié)果。
- onResponse(Call call, Response response)方法是請求成功的回調(diào),可以在里面進行成功的數(shù)據(jù)處理
- onFailure(Call call, IOException e) 方法是請求失敗的回調(diào),可以在里面進行失敗的數(shù)據(jù)處理
接下來我們通過以上代碼異步請求數(shù)來展示出來
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//異步請求失敗之后的回調(diào)
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//異步請求成功之后的回調(diào)
txtView.setText(response.body().string ());
}
});
我們運行看結(jié)果:

image.png
app 出錯了...? 什么原因呢?我們看下錯誤信息

image.png

image.png
錯誤說:只有UI線程才能去更新控件
txtView.setText(response.body().string ());
也就說明我們這段顯示響應(yīng)信息的代碼是在子線程中執(zhí)行的。從而反應(yīng)出我們的 new Callback() 回調(diào)方法并不是在我們的主線程里,而是在子線程里。
那我們改造下代碼,將顯示響應(yīng)信息放在主線程中再去執(zhí)行。
//第四步 call對象調(diào)用enqueue()方法,通過Callback()回調(diào)拿到響應(yīng)體Response
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//異步請求失敗之后的回調(diào)
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//異步請求成功之后的回調(diào)
final String str = response.body().string ();
runOnUiThread(new Runnable() {
@Override
public void run() {
txtView.setText(str);
}
});
}
});

這樣就沒有問題了!
注意事項:onResponse() 和 onFailure() 兩個回調(diào)方法都是在工作線程也就是子線程當中去執(zhí)行的
這里異步請求就完成了。