紧接着上篇说的任务2:异步请求采用UI线程回调方式。
首先采用Handler进行线程间的通信,顺便优化下回调方法,加入HttpInfo以做到工具类使用的渗透性。
在OkHttpUtil中声明一个自定义的异步回调接口,该接口对网络请求接口进行了封装,使同步、异步请求处理流程保持一致性,代码如下:
/**
* 异步请求回调接口
*/
public interface CallbackOk {
/**
* 该回调方法已切换到UI线程
*/
void onResponse(HttpInfo info) throws IOException;
}
在OkHttpUtil中增加Handler业务调度代码:
private final static int WHAT_CALLBACK = 1;
/**
* 主线程业务调度
*/
private static Handler handler = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(Message msg) {
final int what = msg.what;
switch (what){
case WHAT_CALLBACK:
try {
CallbackMessage callMsg = (CallbackMessage) msg.obj;
callMsg.callback.onResponse(callMsg.info);
}catch (Exception e){
e.printStackTrace();
}
break;
}
}
};
修改OkHttpUtil中异步请求方法:
/**
* 异步请求
* @param info
* @param method
* @param callback
*/
private void doRequestAsync(HttpInfo info, Method method, CallbackOk callback){
if(null == callback)
throw new NullPointerException("CallbackOk is null that not allowed");
Call call = httpClient.newCall(fetchRequest(info,method));
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
showLog(e.getMessage());
}
@Override
public void onResponse(Call call, Response res) throws IOException {
//主线程回调
handler.sendMessage(new CallbackMessage(WHAT_CALLBACK,callback,dealResponse(info,res)).build());
}
});
putCall(info,call);
}
这样逻辑应该很清晰了,异步请求后通知Handler进行回调,Handler负责线程的通信(即回调),这里CallbackMessage是对Messay进行了包裹,增加了CallbackOk与HttpInfo属性。
/**
* 回调信息实体类
*/
public class CallbackMessage{
public int what;
public CallbackOk callback;
public HttpInfo info;
public CallbackMessage(int what, CallbackOk callback, HttpInfo info) {
this.what = what;
this.callback = callback;
this.info = info;
}
public Message build(){
Message msg = new Message();
msg.what = this.what;
msg.obj = this;
return msg;
}
}
private HttpInfo dealResponse(HttpInfo info, Response res){
try {
if(null != res && null != res.body()){
if(res.isSuccessful()){
return retInfo(info,info.SUCCESS,res.body().string());
}else{
showLog("HttpStatus: "+res.code());
if(res.code() == 404)//请求页面路径错误
return retInfo(info,info.CheckURL);
if(res.code() == 500)//服务器内部错误
return retInfo(info,info.NoResult);
if(res.code() == 502)//错误网关
return retInfo(info,info.CheckNet);
if(res.code() == 504)//网关超时
return retInfo(info,info.CheckNet);
}
}
return retInfo(info,info.CheckURL);
} catch (Exception e) {
return retInfo(info,info.NoResult);
}
}
下面我们来看下Activity/Fragment的异步网络请求代码:
private void doHttpAsync() {
OkHttpUtil.Builder().build().doGetAsync(HttpInfo.Builder().setUrl(url).build(this), info -> {
if (info.isSuccessful()) {
String ret = info.getRetDetail();
tv_content.setText(ret);
}
});
}
可以看出onResponse回调方法已经是在UI线程了,可以尽情修改界面,再也不用runOnUIThread包裹,这里采用了Lambda表达式,代码看起来是不是清爽多了。
项目已上传至GitHub:https://github.com/MrZhousf/OkHttp3