博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android -- OkHttp的简单使用和封装
阅读量:6607 次
发布时间:2019-06-24

本文共 20742 字,大约阅读时间需要 69 分钟。

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

 效果如下: 

  

  注意,由于我们调用的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());            }        });

  看一下我们服务器的断点

  

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

  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
{ //这是请求数据的返回类型,包含常见的(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
DEFAULT_RESULT_CALLBACK = new ResultCallback
(){ @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
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
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
{ 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
{ private String code; private List
data; private String message; public String getCode() { return code; } public void setCode(String code) { this.code = code; } public List
getData() { return data; } public void setData(List
data) { this.data = data; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; }}

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

  我们创建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
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
getModules() { return modules; } public void setModules(List
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
params = new HashMap(); params.put("username", "superadmin"); params.put("pwd", "ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413"); OkHttpClientManager.postAsyn(url, params, new ResultCallback
>() { @Override public void onError(Request request, Exception e) { } @Override public void onResponse(CommonResultBean
response) { if (response.getData() != null) { UserMenu userMenu = response.getData(); tv_message.setText(userMenu.getReal_name()); progressBar.setVisibility(View.GONE); } } }); }}

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

 See You Next Time···

 

  

 

  

转载于:https://www.cnblogs.com/wjtaigwh/p/6210534.html

你可能感兴趣的文章
python操作数据库-安装
查看>>
指针和引用的区别
查看>>
vs.net删除转移文件
查看>>
你真的了解interface和内部类么
查看>>
java中常用的类型转换
查看>>
【log4j】使用Log4j?,slf4j更轻巧高效
查看>>
第三章 创建命令
查看>>
kuangbin专题七 POJ3264 Balanced Lineup (线段树最大最小)
查看>>
JS动画效果链接汇总
查看>>
父类转为子类涉及到的安全问题
查看>>
网络流,流水线模拟
查看>>
知识点笔记
查看>>
陈云川的OPENLDAP系列
查看>>
django 模型-----自连接
查看>>
P1197 [JSOI2008]星球大战
查看>>
将某个目录下的 文件(字符窜) 只将数字过滤出来
查看>>
urllib模块
查看>>
XML转义字符
查看>>
【vue】vue +element 搭建及开发中项目中,遇到的错误提示
查看>>
微信小程序之简单记账本开发记录(六)
查看>>