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

Android OkHttp的简单使用和封装详解

程序员文章站 2024-02-23 15:53:16
android okhttp的简单使用和封装详解 1,昨天把okhttp仔细的看了一下,以前都是调用同事封装好了的网络框架,直接使用很容易,但自己封装却不是那么简单,还好...

android okhttp的简单使用和封装详解

1,昨天把okhttp仔细的看了一下,以前都是调用同事封装好了的网络框架,直接使用很容易,但自己封装却不是那么简单,还好,今天就来自我救赎一把,就和大家写写从最基础的okhttp的简单get、post的使用,再到它的封装。

2,okhttp的简单使用

  首先我们创建一个工程,并在布局文件中添加三个控件,textview(用于展示获取到json后的信息)、button(点击开始请求网络)、progressbar(网络加载提示框)

  ①简单的异步get请求

  第一步,创建okhttpclient对象

  第二步,创建request请求

  第三步,创建一个call对象

  第四步,将请求添加到调度中

  不多说,直接上代码:

//okhttp的基本使用 --- get方法
  string url = "https://api.douban.com/v2/movie/top250?start=0&count=10";
  //1,创建okhttpclient对象
  okhttpclient mokhttpclient = new okhttpclient();
  //2,创建一个request
  request request = new request.builder().url(url).build();
  //3,创建一个call对象
  call call = mokhttpclient.newcall(request);
  //4,将请求添加到调度中
  call.enqueue(new callback() {
    @override
    public void onfailure(request request, ioexception e) {
 
    }
 
    @override
    public void onresponse(response response) throws ioexception {
      if (response.issuccessful()) {
        final string message = response.body().string();
        handler.post(new runnable() {
          @override
          public void run() {
            tv_message.settext(message);
            progressbar.setvisibility(view.gone);
          }
        });
 
      }
    }
 
  });

 效果如下: 

  Android OkHttp的简单使用和封装详解

  注意,由于我们调用的enqueue()方法,是运行在网络线程中的,所以当我们得到json数据后想要获取更新ui的话,可以开使用handle.post()方法在run方法里面更新ui。

  ② 简单的异步post请求

  这里的post请求我们以最常见的注册登录来举例。post请求的步骤和get是相似的只是在创建request的 时候将服务器需要的参数传递进去.

  代码如下:

string url = "http://192.168.1.123:8081/api/login";
    //1,创建okhttpclient对象
    okhttpclient mokhttpclient = new okhttpclient();
    //2,创建request
    requestbody formbody = new formencodingbuilder()
        .add("username", "superadmin")
        .add("pwd", "ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413")
        .build();
 
    request request = new request.builder().url(url).post(formbody).build();
    //3,创建call对象并将请求对象添加到调度中
    mokhttpclient.newcall(request).enqueue(new callback() {
      @override
      public void onfailure(request request, ioexception e) {
 
      }
 
      @override
      public void onresponse(response response) throws ioexception {
        log.i("wangjitao", response.body().string());
      }
    });

  看一下我们服务器的断点

Android OkHttp的简单使用和封装详解  

  可以看到我们服务器的确拿到了我们传递参数,再看一下我们请求后拿到的数据

Android OkHttp的简单使用和封装详解

  ok,这样的话我们的post方法就没什么问题了

3,okhttp的封装

由于是封装我们可以吧okhttp和gson给结合起来,那么我们在gradle文件添加以下的依赖

compile "com.squareup.okhttp:okhttp:2.4.0"
compile 'com.squareup.okio:okio:1.5.0'
compile "com.google.code.gson:gson:2.8.0"

  ①callback的创建  

  首选我们知道,当接口请求成功或者失败的时候我们需要将这个信息通知给用户,那么我们就需要创建一个抽象类requestcallback,请求前、成功、失败、请求后这几个方法,创建onbefore()、onafter()、onerror()、onresponse()对应

/**
 * 在请求之前的方法,一般用于加载框展示
 *
 * @param request
 */
public void onbefore(request request) {
}
 
/**
 * 在请求之后的方法,一般用于加载框隐藏
 */
public void onafter() {
}
 
/**
 * 请求失败的时候
 *
 * @param request
 * @param e
 */
public abstract void onerror(request request, exception e);
 
/**
 *
 * @param response
 */
public abstract void onresponse(t response);

 由于我们每次想要的数据不一定,所以这里我们用<t>来接收想要装成的数据格式,并通过反射得到想要的数据类型(一般是bean、list)之类 ,所以requestcallback的整体代码如下:

package com.qianmo.httprequest.http;
 
import com.google.gson.internal.$gson$types;
import com.squareup.okhttp.request;
 
import java.lang.reflect.parameterizedtype;
import java.lang.reflect.type;
 
 
/**
 * created by wangjitao on 15/10/16.
 * 抽象类,用于请求成功后的回调
 */
public abstract class resultcallback<t> {
  //这是请求数据的返回类型,包含常见的(bean,list等)
  type mtype;
 
  public resultcallback() {
    mtype = getsuperclasstypeparameter(getclass());
  }
 
  /**
   * 通过反射想要的返回类型
   *
   * @param subclass
   * @return
   */
  static type getsuperclasstypeparameter(class<?> subclass) {
    type superclass = subclass.getgenericsuperclass();
    if (superclass instanceof class) {
      throw new runtimeexception("missing type parameter.");
    }
    parameterizedtype parameterized = (parameterizedtype) superclass;
    return $gson$types.canonicalize(parameterized.getactualtypearguments()[0]);
  }
 
  /**
   * 在请求之前的方法,一般用于加载框展示
   *
   * @param request
   */
  public void onbefore(request request) {
  }
 
  /**
   * 在请求之后的方法,一般用于加载框隐藏
   */
  public void onafter() {
  }
 
  /**
   * 请求失败的时候
   *
   * @param request
   * @param e
   */
  public abstract void onerror(request request, exception e);
 
  /**
   *
   * @param response
   */
  public abstract void onresponse(t response);
}

  ②对get、post方法的简单封装 

  首先我们创建一个okhttpclientmanager类,由于是管理类,所以,单例加静态对象搞起

private static okhttpclientmanager minstance;
 
 public static okhttpclientmanager getinstance() {
    if (minstance == null){
      synchronized (okhttpclientmanager.class) {
        if (minstance == null) {
          minstance = new okhttpclientmanager();
        }
      }
    }
    return minstance;
  }

 在创建manager对象的时候我们要把okhttp的一些参数配置一下,顺便一提一下,由于我们我们异步get、post方法是运行在子线程中,所以这里我们添加了分发的 handler mdelivery;,重写的okhttpclientmanager构造方法如下:

private okhttpclientmanager() {
    mokhttpclient = new okhttpclient();
    mokhttpclient.setconnecttimeout(10, timeunit.seconds);
    mokhttpclient.setwritetimeout(10, timeunit.seconds);
    mokhttpclient.setreadtimeout(30, timeunit.seconds);
    //cookie enabled
    mokhttpclient.setcookiehandler(new cookiemanager(null, cookiepolicy.accept_original_server));
    mdelivery = new handler(looper.getmainlooper());
    mgson = new gson();
  }

  前面的外部调用对象封装好了,这里我们开始来封装get或post方法,我这里以post方法为例子,首先分析一下,post方法会有几个参数,参数一url,参数二参数params,参数三callback(及我们上面的requestcallback)参数四flag(用于取消请求操作,可为空),基础代码如下:

/**
    * 通用基础的异步的post请求
    * @param url
    * @param callback
    * @param tag
    */
    public void postasyn(string url, param[] params, final resultcallback callback, object tag) {
      request request = buildpostformrequest(url, params, tag);
      deliveryresult(callback, request);
    }

  那么我们再看一下deliveryresult方法到底是干什么的

/**
  * 请求回调处理方法并传递返回值
  * @param callback map类型请求参数
  * @param request request请求
  */
  private void deliveryresult(resultcallback callback, request request) {
    if (callback == null)
      callback = default_result_callback;
    final resultcallback rescallback = callback;
    //ui thread
    callback.onbefore(request);
    mokhttpclient.newcall(request).enqueue(new callback() {
      @override
      public void onfailure(final request request, final ioexception e) {
        sendfailedstringcallback(request, e, rescallback);
      }
 
      @override
      public void onresponse(final response response) {
        try {
          final string responsemessage=response.message();
          final string responsebody = response.body().string();
          if(response.code()==200){
            if (rescallback.mtype == string.class) {
              sendsuccessresultcallback(responsebody, rescallback);
            } else {
              object o = mgson.fromjson(responsebody, rescallback.mtype);
              sendsuccessresultcallback(o, rescallback);
            }
          }else{
            exception exception=new exception(response.code()+":"+responsemessage);
            sendfailedstringcallback(response.request(), exception, rescallback);
          }
        } catch (ioexception e) {
          sendfailedstringcallback(response.request(), e, rescallback);
        } catch (com.google.gson.jsonparseexception e) {//json解析的错误
          sendfailedstringcallback(response.request(), e, rescallback);
        }
      }
    });
  }

  可以看到,这个方法主要是发出请求并对请求后的数据开始回调,这样我们就基本上封装好了一个post方法了  ,把代码这一部分的代码贴出来看看

public class okhttpclientmanager {
  private static final string tag = "com.qianmo.httprequest.http.okhttpclientmanager";
 
  private static okhttpclientmanager minstance;
  //默认的请求回调类
  private final resultcallback<string> default_result_callback = new resultcallback<string>(){
    @override
    public void onerror(request request, exception e) {}
 
    @override
    public void onresponse(string response) {}
  };
  private okhttpclient mokhttpclient;
  private handler mdelivery;
  private gson mgson;
  private getdelegate mgetdelegate = new getdelegate();
  private postdelegate mpostdelegate = new postdelegate();
  private downloaddelegate mdownloaddelegate = new downloaddelegate();
 
  private okhttpclientmanager() {
    mokhttpclient = new okhttpclient();
    mokhttpclient.setconnecttimeout(10, timeunit.seconds);
    mokhttpclient.setwritetimeout(10, timeunit.seconds);
    mokhttpclient.setreadtimeout(30, timeunit.seconds);
    //cookie enabled
    mokhttpclient.setcookiehandler(new cookiemanager(null, cookiepolicy.accept_original_server));
    mdelivery = new handler(looper.getmainlooper());
    mgson = new gson();
  }
 
  public static okhttpclientmanager getinstance() {
    if (minstance == null){
      synchronized (okhttpclientmanager.class) {
        if (minstance == null) {
          minstance = new okhttpclientmanager();
        }
      }
    }
    return minstance;
  }
 
  /**
   * 外部可调用的post异步请求方法
   * @param url 请求url
   * @param params
   * @param callback 请求完成后回调类
   */
  public static void postasyn(string url, map<string, string> params, final resultcallback callback) {
    getinstance().getpostdelegate().postasyn(url, params, callback, null);
  }
 
  /**
     * 异步的post请求
     * @param url
     * @param params
     * @param callback
     * @param tag
     */
    public void postasyn(string url, map<string, string> params, final resultcallback callback, object tag) {
      param[] paramsarr = map2params(params);
      postasyn(url, paramsarr, callback, tag);
    }
  /**
     * 通用基础的异步的post请求
     * @param url
     * @param callback
     * @param tag
     */
    public void postasyn(string url, param[] params, final resultcallback callback, object tag) {
      request request = buildpostformrequest(url, params, tag);
      deliveryresult(callback, request);
    }
   
  /**
   * 请求回调处理方法并传递返回值
   * @param callback map类型请求参数
   * @param request request请求
   */
  private void deliveryresult(resultcallback callback, request request) {
    if (callback == null)
      callback = default_result_callback;
    final resultcallback rescallback = callback;
    //ui thread
    callback.onbefore(request);
    mokhttpclient.newcall(request).enqueue(new callback() {
      @override
      public void onfailure(final request request, final ioexception e) {
        sendfailedstringcallback(request, e, rescallback);
      }
 
      @override
      public void onresponse(final response response) {
        try {
          final string responsemessage=response.message();
          final string responsebody = response.body().string();
          if(response.code()==200){
            if (rescallback.mtype == string.class) {
              sendsuccessresultcallback(responsebody, rescallback);
            } else {
              object o = mgson.fromjson(responsebody, rescallback.mtype);
              sendsuccessresultcallback(o, rescallback);
            }
          }else{
            exception exception=new exception(response.code()+":"+responsemessage);
            sendfailedstringcallback(response.request(), exception, rescallback);
          }
        } catch (ioexception e) {
          sendfailedstringcallback(response.request(), e, rescallback);
        } catch (com.google.gson.jsonparseexception e) {//json解析的错误
          sendfailedstringcallback(response.request(), e, rescallback);
        }
      }
    });
  }
   /**
   * 处理请求成功的回调信息方法
   * @param object 服务器响应信息
   * @param callback 回调类
   */
  private void sendsuccessresultcallback(final object object, final   resultcallback callback) {
    mdelivery.post(() -> {
      callback.onresponse(object);
      callback.onafter();
    });
  }
}  

  这样我们就把post方法封装好了,同理get方法,ok,现在我们可以来调用调用了,在调用之前我们可以对返回数据格式再来封装封装,一般我们后台返回的数据格式是类似如下:

{
 "code": 200,
 "data": {},
 "message": "登录成功"
}

 而data中有可能是对象,也有可能是数组,所以我们用两个类来实现一下

 commonresultbean

package com.qianmo.httprequest.bean;
 
/**
 * 服务端返回通用接收实体
 * created by wangjitao on 15/10/30.
 */
public class commonresultbean<t> {
  private string code;
  private t data;
  private string message;
 
  public string getcode() {
    return code;
  }
 
  public void setcode(string code) {
    this.code = code;
  }
 
  public t getdata() {
    return data;
  }
 
  public void setdata(t data) {
    this.data = data;
  }
 
  public string getmessage() {
    return message;
  }
 
  public void setmessage(string message) {
    this.message = message;
  }
}

 commonresultlistbean

package com.qianmo.httprequest.bean;
 
import java.util.list;
 
/**
 * 服务端返回带有list数据的通用接收实体
 * created by wangjitao on 15/12/1.
 */
public class commonresultlistbean<t> {
  private string code;
  private list<t> data;
  private string message;
 
  public string getcode() {
    return code;
  }
 
  public void setcode(string code) {
    this.code = code;
  }
 
  public list<t> getdata() {
    return data;
  }
 
  public void setdata(list<t> data) {
    this.data = data;
  }
 
  public string getmessage() {
    return message;
  }
 
  public void setmessage(string message) {
    this.message = message;
  }
}

  ok,现在还是以上面我们登录的接口为例子开始我们的方法调用,返回的数据格式如图所示

Android OkHttp的简单使用和封装详解

  我们创建usermenu.java类

package com.qianmo.httprequest.bean;
 
import java.util.list;
 
/**
 * created by wangjitao on 2016/12/21 0021.
 * e-mail:543441727@qq.com
 * 用户菜单权限按钮
 */
public class usermenu {
 
  /**
   * last_login_time : 2016-12-21 15:40:28
   * member_id : 1
   * modules : []
   * phone : 18900532225
   * real_name : 超级管理员
   * role : {"role_id":1,"role_name":"超级管理员"}
   * username : superadmin
   */
 
  private string last_login_time;
  private int member_id;
  private string phone;
  private string real_name;
  /**
   * role_id : 1
   * role_name : 超级管理员
   */
 
  private rolebean role;
  private string username;
  /**
   * module_code : 100
   * module_id : 1
   * module_name : 首页
   * pid : 0
   * type : 1
   * value : p_index
   */
 
  private list<modulesbean> modules;
 
  public string getlast_login_time() {
    return last_login_time;
  }
 
  public void setlast_login_time(string last_login_time) {
    this.last_login_time = last_login_time;
  }
 
  public int getmember_id() {
    return member_id;
  }
 
  public void setmember_id(int member_id) {
    this.member_id = member_id;
  }
 
  public string getphone() {
    return phone;
  }
 
  public void setphone(string phone) {
    this.phone = phone;
  }
 
  public string getreal_name() {
    return real_name;
  }
 
  public void setreal_name(string real_name) {
    this.real_name = real_name;
  }
 
  public rolebean getrole() {
    return role;
  }
 
  public void setrole(rolebean role) {
    this.role = role;
  }
 
  public string getusername() {
    return username;
  }
 
  public void setusername(string username) {
    this.username = username;
  }
 
  public list<modulesbean> getmodules() {
    return modules;
  }
 
  public void setmodules(list<modulesbean> modules) {
    this.modules = modules;
  }
 
  public static class rolebean {
    private int role_id;
    private string role_name;
 
    public int getrole_id() {
      return role_id;
    }
 
    public void setrole_id(int role_id) {
      this.role_id = role_id;
    }
 
    public string getrole_name() {
      return role_name;
    }
 
    public void setrole_name(string role_name) {
      this.role_name = role_name;
    }
  }
 
  public static class modulesbean {
    private string module_code;
    private int module_id;
    private string module_name;
    private int pid;
    private int type;
    private string value;
 
    public string getmodule_code() {
      return module_code;
    }
 
    public void setmodule_code(string module_code) {
      this.module_code = module_code;
    }
 
    public int getmodule_id() {
      return module_id;
    }
 
    public void setmodule_id(int module_id) {
      this.module_id = module_id;
    }
 
    public string getmodule_name() {
      return module_name;
    }
 
    public void setmodule_name(string module_name) {
      this.module_name = module_name;
    }
 
    public int getpid() {
      return pid;
    }
 
    public void setpid(int pid) {
      this.pid = pid;
    }
 
    public int gettype() {
      return type;
    }
 
    public void settype(int type) {
      this.type = type;
    }
 
    public string getvalue() {
      return value;
    }
 
    public void setvalue(string value) {
      this.value = value;
    }
  }
 
}

  所以mainactivity代码如下:

package com.qianmo.httprequest;
 
import android.os.environment;
import android.os.handler;
import android.support.v7.app.appcompatactivity;
import android.os.bundle;
import android.util.log;
import android.view.view;
import android.view.view.onclicklistener;
import android.widget.button;
import android.widget.progressbar;
import android.widget.textview;
 
import com.qianmo.httprequest.bean.commonresultbean;
import com.qianmo.httprequest.bean.usermenu;
import com.qianmo.httprequest.http.irequestcallback;
import com.qianmo.httprequest.http.irequestmanager;
import com.qianmo.httprequest.http.okhttpclientmanager;
import com.qianmo.httprequest.http.requestfactory;
import com.qianmo.httprequest.http.resultcallback;
import com.squareup.okhttp.call;
import com.squareup.okhttp.callback;
import com.squareup.okhttp.formencodingbuilder;
import com.squareup.okhttp.okhttpclient;
import com.squareup.okhttp.request;
import com.squareup.okhttp.requestbody;
import com.squareup.okhttp.response;
 
import java.io.file;
import java.io.ioexception;
import java.util.hashmap;
import java.util.map;
 
 
public class mainactivity extends appcompatactivity implements onclicklistener {
  private handler handler;
  private textview tv_message;
  private button btn_login;
  private progressbar progressbar;
 
  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_main);
    tv_message = (textview) findviewbyid(r.id.tv_message);
    btn_login = (button) findviewbyid(r.id.btn_login);
    progressbar = (progressbar) findviewbyid(r.id.progressbar);
    handler = new handler();
    btn_login.setonclicklistener(this);
  }
 
  @override
  public void onclick(view view) {
    progressbar.setvisibility(view.visible);
 
 
    string url = "http://192.168.1.123:8081/api/login";
    map<string, string> params = new hashmap();
    params.put("username", "superadmin");
    params.put("pwd", "ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413");
    okhttpclientmanager.postasyn(url, params,
        new resultcallback<commonresultbean<usermenu>>() {
          @override
          public void onerror(request request, exception e) {
 
          }
 
          @override
          public void onresponse(commonresultbean<usermenu> response) {
            if (response.getdata() != null) {
              usermenu usermenu = response.getdata();
              tv_message.settext(usermenu.getreal_name());
              progressbar.setvisibility(view.gone);
            }
          }
        });
 
  }
}

  这样我们就可以简单的调用了,最后看一下我们的效果:

Android OkHttp的简单使用和封装详解

 see you next time···

 感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!