okhttp 除了支持常用的同步 http 请求之外,还支持异步 http 请求调用。在使用同步调用时,当前线程会被阻塞,直到 http 请求完成。当同时发出多个 http 请求时,同步调用的性能会比较差。这个时候通过异步调用可以提高整体的性能。
在通过 newcall 方法创建一个新的 call 对象之后,不是通过 execute 方法来同步执行,而是通过 enqueue 方法来添加到执行队列中。在调用 enqueue 方法时需要提供一个 callback 接口的实现。在 callback 接口实现中,通过 onresponse 和 onfailure 方法来处理响应和进行错误处理。
异步调用的示例
public class asyncget { public static void main(string[] args) throws ioexception { okhttpclient client = new okhttpclient(); request request = new request.builder() .url("http://www.baidu.com") .build(); client.newcall(request).enqueue(new callback() { public void onfailure(request request, ioexception e) { e.printstacktrace(); } public void onresponse(response response) throws ioexception { if (!response.issuccessful()) { throw new ioexception("服务器端错误: " + response); } system.out.println(response.body().string()); } }); } }
觉得okhttp最难写的地方应该就是callback了。
相信很多人都会遇到,如果callback回来之后,我的activity finish了,或是我的fragment replace了。
此时更改ui,就会产生找不到view的问题。
而且callback回来,居然是在backgroundthread上,
这时候如果要操作view又要切换到mainthread去,略显麻烦。
所以我在写的时候,是没有使用callback的 以下提供一种漂亮(自认...)的写法给大家做参考。
/* 以fragment为例 */ public class basefragment extends fragment implements handler.callback { private static final int msg_query_data = 0x00; private static final int msg_display_data = 0x01; @override public void onattach(activity activity) { super.onattach(activity); this.activity = activity; /* setup handler */ handlerthread handlerthread = new handlerthread(getclass().getname()); handlerthread.start(); backgroundhandler = new handler(handlerthread.getlooper(), this); uihandler = new handler(activity.getmainlooper(), this); } @override public void onviewcreated(view view, @nullable bundle savedinstancestate) { /* start */ backgroundhandler.sendemptymessage(msg_query_data); } @override public void ondestroyview() { /* 將message清空,backgroundthread結束掉 */ backgroundhandler.removecallbacksandmessages(null); uihandler.removecallbacksandmessages(null); backgroundhandler.getlooper().quit(); super.ondestroyview(); } @override public boolean handlemessage(message msg) { /* 如果fragment不在activity上了,直接return掉,避免npe */ if (!isadded()) return false; /* 做各種msg */ switch(msg.what){ case msg_query_data: // do okhttp without callback response response = client.newcall(request).execute(); // 傳回 uithread 做ui更新 message respmsg = uihandler.obtainmessage(); respmsg.what = msg_display_data; respmsg.obj = response; backgroundhandler.sendmessage(respmsg); break; case msg_display_data: response apiresponse = (response)msg.obj; // 失敗 if(null == apiresponse){ //show error } // 成功 else{ //display data on ui } break; return false; } }
如对本文有疑问, 点击进行留言回复!!
Codeforces C. A Cookie for You (模拟 / 分类 / 贪心) (Round #654 Div.2)
DialogFragment弹窗(带黑色透明背景和不带黑色透明背景)
网友评论