详解Android的OkHttp包编写异步HTTP请求调用的方法
OkHttp除了支持常用的同步HTTP请求之外,还支持异步HTTP请求调用。在使用同步调用时,当前线程会被阻塞,直到HTTP请求完成。当同时发出多个HTTP请求时,同步调用的性能会比较差。这个时候通过异步调用可以提高整体的性能。
在通过newCall方法创建一个新的Call对象之后,不是通过execute方法来同步执行,而是通过enqueue方法来添加到执行队列中。在调用enqueue方法时需要提供一个Callback接口的实现。在Callback接口实现中,通过onResponse和onFailure方法来处理响应和进行错误处理。
异步调用的示例
publicclassAsyncGet{
publicstaticvoidmain(String[]args)throwsIOException{
OkHttpClientclient=newOkHttpClient();
Requestrequest=newRequest.Builder()
.url("http://www.baidu.com")
.build();
client.newCall(request).enqueue(newCallback(){
publicvoidonFailure(Requestrequest,IOExceptione){
e.printStackTrace();
}
publicvoidonResponse(Responseresponse)throwsIOException{
if(!response.isSuccessful()){
thrownewIOException("服务器端错误:"+response);
}
System.out.println(response.body().string());
}
});
}
}
觉得okHttp最难写的地方应该就是Callback了。
相信很多人都会遇到,如果Callback回来之后,我的Activityfinish了,或是我的Fragmentreplace了。
此时更改UI,就会产生找不到View的问题。
而且Callback回来,居然是在backgroundThread上,
这时候如果要操作View又要切换到mainThread去,略显麻烦。
所以我在写的时候,是没有使用Callback的以下提供一种漂亮(自认...)的写法给大家做参考。
/*以fragment为例*/
publicclassBaseFragmentextendsFragmentimplementsHandler.Callback{
privatestaticfinalintMSG_QUERY_DATA=0x00;
privatestaticfinalintMSG_DISPLAY_DATA=0x01;
@Override
publicvoidonAttach(Activityactivity){
super.onAttach(activity);
this.activity=activity;
/*setuphandler*/
HandlerThreadhandlerThread=newHandlerThread(getClass().getName());
handlerThread.start();
backgroundHandler=newHandler(handlerThread.getLooper(),this);
uiHandler=newHandler(activity.getMainLooper(),this);
}
@Override
publicvoidonViewCreated(Viewview,@NullableBundlesavedInstanceState){
/*start*/
backgroundHandler.sendEmptyMessage(MSG_QUERY_DATA);
}
@Override
publicvoidonDestroyView(){
/*將Message清空,backgroundThread結束掉*/
backgroundHandler.removeCallbacksAndMessages(null);
uiHandler.removeCallbacksAndMessages(null);
backgroundHandler.getLooper().quit();
super.onDestroyView();
}
@Override
publicbooleanhandleMessage(Messagemsg){
/*如果fragment不在Activity上了,直接return掉,避免NPE*/
if(!isAdded())returnfalse;
/*做各種MSG*/
switch(msg.what){
caseMSG_QUERY_DATA:
//dookHttpwithoutcallback
Responseresponse=client.newCall(request).execute();
//傳回uiThread做UI更新
MessagerespMsg=uiHandler.obtainMessage();
respMsg.what=MSG_DISPLAY_DATA;
respMsg.obj=response;
backgroundHandler.sendMessage(respMsg);
break;
caseMSG_DISPLAY_DATA:
ResponseapiResponse=(Response)msg.obj;
//失敗
if(null==apiResponse){
//showerror
}
//成功
else{
//displaydataonUI
}
break;
returnfalse;
}
}