欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

详解Android的OkHttp包编写异步HTTP请求调用的方法

程序员文章站 2024-03-31 18:02:52
okhttp 除了支持常用的同步 http 请求之外,还支持异步 http 请求调用。在使用同步调用时,当前线程会被阻塞,直到 http 请求完成。当同时发出多个 http...

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;
  }
}