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

     效果如下: 

      

      注意,由于我们调用的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<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,现在还是以上面我们登录的接口为例子开始我们的方法调用,返回的数据格式如图所示

      我们创建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);
                            }
                        }
                    });
    
        }
    }
    

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

     See You Next Time···

     

      

     

      

  • 相关阅读:
    个人号微信机器人接口
    js tree 根据子节点找到所有父节点
    大数据分析之纳税人画像-实现和优化思路
    前后端分离项目安全漏洞修复总结
    多租户&多账户&多公众号_saas微信公众平台设计思路
    java7 try-with-resources 很香
    java7 异常处理增强
    java7 try-with-resources 很香
    mysql 按分数段,每个专业分数段统计人数
    一文看懂奈奎斯特定理和香农定理
  • 原文地址:https://www.cnblogs.com/wjtaigwh/p/6210534.html
Copyright © 2020-2023  润新知