美文网首页Android开发之路
基于OkGo(OkHttp)的统一请求响应小封装

基于OkGo(OkHttp)的统一请求响应小封装

作者: 阿敏其人 | 来源:发表于2018-09-11 11:59 被阅读1090次

    OkGo基于OkHttp。
    我们根据OkGo做一点小封装。
    OkHttp的Converter很好用,但是,String更加灵活,我们这里不用Converter。

    特点

    • 请求统一入口
      方便统一处理,比如请求头添加参数之类的
    • 响应统一处理,也可指定单独处理
      默认统一处理,返回格式比较特殊的可单独处理
    • request和response打印
      看请求参数,看响应内容,结合Ohkttp的拦截器
    • 省缺模式选择复写回调接口
      每次都只复写onSuccess和onFinish,需要onError和onStart之类,再选择性复写

    小封装开始

    OkGo配置

    1、应用级gradle

     implementation 'com.lzy.net:okgo:3.0.4'
    

    2、Applicaiton初始化

    public class MyApplication extends Application{
        @Override
        public void onCreate() {
            super.onCreate();
            initOkGo();
    
        }
    
        private void initOkGo() {
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor("OkGo");
            //log打印级别,决定了log显示的详细程度
            loggingInterceptor.setPrintLevel(HttpLoggingInterceptor.Level.BODY);
            //log颜色级别,决定了log在控制台显示的颜色
            loggingInterceptor.setColorLevel(Level.INFO);
            builder.addInterceptor(loggingInterceptor);
    
            //全局的读取超时时间  基于前面的通道建立完成后,客户端终于可以向服务端发送数据了
            builder.readTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);
            //全局的写入超时时间  服务器发回消息,可是客户端出问题接受不到了
            builder.writeTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);
            //全局的连接超时时间  http建立通道的时间
            builder.connectTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);
    
            //使用sp保持cookie,如果cookie不过期,则一直有效
            builder.cookieJar(new CookieJarImpl(new SPCookieStore(this)));
            //使用数据库保持cookie,如果cookie不过期,则一直有效
            //builder.cookieJar(new CookieJarImpl(new DBCookieStore(this)));
            //使用内存保持cookie,app退出后,cookie消失
            //builder.cookieJar(new CookieJarImpl(new MemoryCookieStore()));
    
    
            //  === 配置https ===
            //方法一:信任所有证书,不安全有风险
            /*HttpsUtils.SSLParams sslParams1 = HttpsUtils.getSslSocketFactory();
            //方法二:自定义信任规则,校验服务端证书
            HttpsUtils.SSLParams sslParams2 = HttpsUtils.getSslSocketFactory(new SafeTrustManager());
            //方法三:使用预埋证书,校验服务端证书(自签名证书)
            HttpsUtils.SSLParams sslParams3 = HttpsUtils.getSslSocketFactory(getAssets().open("srca.cer"));
            //方法四:使用bks证书和密码管理客户端证书(双向认证),使用预埋证书,校验服务端证书(自签名证书)
            HttpsUtils.SSLParams sslParams4 = HttpsUtils.getSslSocketFactory(getAssets().open("xxx.bks"), "123456", getAssets().open("yyy.cer"));
            builder.sslSocketFactory(sslParams1.sSLSocketFactory, sslParams1.trustManager);
            //配置https的域名匹配规则,详细看demo的初始化介绍,不需要就不要加入,使用不当会导致https握手失败
            builder.hostnameVerifier(new SafeHostnameVerifier());*/
    
            //  === 请求头 和 参数的 设置 ===
            //---------这里给出的是示例代码,告诉你可以这么传,实际使用的时候,根据需要传,不需要就不传-------------//
            /*HttpHeaders headers = new HttpHeaders();
            headers.put("commonHeaderKey1", "commonHeaderValue1");    //header不支持中文,不允许有特殊字符
            headers.put("commonHeaderKey2", "commonHeaderValue2");
            HttpParams params = new HttpParams();
            params.put("commonParamsKey1", "commonParamsValue1");     //param支持中文,直接传,不要自己编码
            params.put("commonParamsKey2", "这里支持中文参数");*/
    
            OkGo.getInstance().init(this)                       //必须调用初始化
                    .setOkHttpClient(builder.build())               //建议设置OkHttpClient,不设置将使用默认的
                    .setCacheMode(CacheMode.NO_CACHE)               //全局统一缓存模式,默认不使用缓存,可以不传
                    .setCacheTime(CacheEntity.CACHE_NEVER_EXPIRE)   //全局统一缓存时间,默认永不过期,可以不传
                    .setRetryCount(3);                            //全局统一超时重连次数,默认为三次,那么最差的情况会请求4次(一次原始请求,三次重连请求),不需要可以设置为0
            //.addCommonHeaders(headers)                      //全局公共头
            //.addCommonParams(params);
        }
    }
    

    AndroidManifest指定一下Application。
    网络权限配置一下。

    封装工具类

    主工具类

    /**
     * User: AMQR
     * Date&Time: 2018-09-11 & 10:36
     * Describe: 这个类存在的意义是为了做请求的统一处理
     * 不要conver转对象,原生数据处理起来才可以灵活变通
     */
    public class OkGoUtils {
        /**
         * 网络请求的相关参数
         */
        public static class RequestOption{
            public Context context;
            public Map params;
            public String url;
            public AbsPostJsonStringCb iPostJsonStringCb;
            /**
             * 是否同意处理response相应码
             * 一般来说都是默认统一处理,当后端部分接口返回不规范的时候,需要单独处理,
             */
            public boolean isNormalDeal = true;
            public JSONObject mJSONObject;
            //public LoadHelpView loadHelpView;
        }
    
    
        /**
         * post请求
         * 以String形式返回数据,以post方式提交,包装这一层,是为了统一处理数据
         */
        public static void postJsonStringCallback(final RequestOption requestOption){
    
    
            JSONObject jsonObject;
            if(requestOption.mJSONObject!=null){
                jsonObject = requestOption.mJSONObject;
            }else{
                jsonObject = new JSONObject(requestOption.params);
            }
    
            OkGo.<String>post(requestOption.url)
                    //.tag()
                    .upJson(jsonObject)
                    .headers("Authorization", "本地存储Token")
                    .execute(new StringCallback() {
                        @Override
                        public void onSuccess(Response<String> response) {
                            String resp = response.body().toString();
                            FortuneLogUtils.d(requestOption.url+"  ======= >>>>>> 请求详情:  "+"\n"+"request:"+requestOption.url+"\n"+"params: "+requestOption.params+"\n"+"response: "+resp);
    
                            // 是否需要 统一的处理
                            if(requestOption.isNormalDeal){
                                if(unifiedProcessingCode(resp, requestOption)){
                                    backToSuccessNormal(resp, requestOption);
                                }
                            }else{
                                backToSuccessOriginal(resp, requestOption);
                            }
                        }
    
                        @Override
                        public void onError(Response<String> response) {
                            super.onError(response);
    
                            FtToastUtil.showShort(requestOption.context,"请求失败,请稍后在试");
                            FortuneLogUtils.d("网络请求异常:"+response.toString());
    
                            if(response.body()!=null){
                                String err = response.body().toString();
                                FortuneLogUtils.e("======= request faile:"+requestOption.url+"\n"+"params: "+requestOption.params+"\n"+"response: "+err);
                            }
    
                            if(requestOption.iPostJsonStringCb !=null){
                                requestOption.iPostJsonStringCb.onError(response);
                            }
    
                        }
    
                        @Override
                        public void onStart(Request<String, ? extends Request> request) {
                            super.onStart(request);
                            if(requestOption.iPostJsonStringCb !=null){
                                requestOption.iPostJsonStringCb.onStart(request);
                            }
                        }
    
                        @Override
                        public void onFinish() {
                            super.onFinish();
                            if(requestOption.iPostJsonStringCb !=null){
                                requestOption.iPostJsonStringCb.onFinish();
                            }
                        }
                    });
        }
    
        /**
         * 返回码的统一处理
         * 当返回 true 时,代表success。
         * @param resp
         * @param requestOption
         * @return
         */
        private static boolean unifiedProcessingCode(String resp, final RequestOption requestOption) {
            if(!TextUtils.isEmpty(resp)){
                try {
                    JSONObject jsonObject = new JSONObject(resp);
                    String code= jsonObject.optString("code");
                    // 假设返回码200为通过
                    if(code.equals("200")){
                        return true;
                    }else if (code.equals("1001")) { // 其他错误码处理
                        FtToastUtil.showShort(requestOption.context, "验证码错误");
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
            return  false;
        }
    
        /**
         * 某些错误码的出现,应该让程序直接抛到登录页面
         * @param requestOption
         * @param content
         */
        private static void gotoLogin(final RequestOption requestOption, String content) {
            // code...
        }
    
    
        /**
         * get请求
         * @param requestOption
         */
        public  static void getJsonStringCallback(final RequestOption requestOption){
    
            if(requestOption.params!=null && requestOption.params.size()>0){
                Map<String,String> map = requestOption.params;
                boolean isFirst = true;
                StringBuffer stringBuffer= new StringBuffer();
                for (Map.Entry<String, String> entry : map.entrySet()) {
                    if(isFirst){
                        stringBuffer.append("?"+entry.getKey()+"="+entry.getValue());
                        isFirst = false;
                    }else{
                        stringBuffer.append("&"+entry.getKey()+"="+entry.getValue());
                    }
                }
                requestOption.url = requestOption.url+stringBuffer.toString();
            }
    
    
            OkGo.<String>get(requestOption.url)
                    // header 参数,如果需要的话
                    .headers("Authorization", "本地存储")
                    //.tag()
                    .execute(new StringCallback() {
                        @Override
                        public void onSuccess(Response<String> response) {
                            String resp = response.body().toString();
                            FortuneLogUtils.d("======= request:"+"\n"+requestOption.url+"\n"+"response: "+resp);
    
                            // 是否需要 统一的处理
                            if(requestOption.isNormalDeal){
                                if(unifiedProcessingCode(resp,requestOption)){
                                    backToSuccessNormal(resp, requestOption);
                                }
                            }else{
                                backToSuccessOriginal(resp, requestOption);
                            }
    
                        }
    
                        @Override
                        public void onError(Response<String> response) {
                            super.onError(response);
                            FtToastUtil.showShort(requestOption.context,"请求失败,请稍后在试");
                            if(response.body()!=null){
                                FortuneLogUtils.d("网络请求异常:"+response.toString());
                                String err = response.body().toString();
                                FortuneLogUtils.e("======= request faile:"+requestOption.url+"\n"+"response: "+err);
                            }
    
                            if(requestOption.iPostJsonStringCb !=null){
                                requestOption.iPostJsonStringCb.onError(response);
                            }
    
                        }
    
                        @Override
                        public void onStart(Request<String, ? extends Request> request) {
                            super.onStart(request);
                            if(requestOption.iPostJsonStringCb !=null){
                                requestOption.iPostJsonStringCb.onStart(request);
                            }
                        }
    
                        @Override
                        public void onFinish() {
                            super.onFinish();
                            if(requestOption.iPostJsonStringCb !=null){
                                requestOption.iPostJsonStringCb.onFinish();
                            }
                        }
                    });
        }
    
        /**
         * 请求success 通用处理
         * @param resp
         * @param requestOption
         */
        private static void backToSuccessNormal(String resp, RequestOption requestOption) {
    
            if(requestOption.iPostJsonStringCb !=null){
                try {
                    JSONObject jsonObject = new JSONObject(resp);
                    String data = jsonObject.getString("data");
                    requestOption.iPostJsonStringCb.onSuccess(resp,data);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 请求成功,原生字符串处理
         * @param resp
         * @param requestOption
         */
        private static void backToSuccessOriginal(String resp, RequestOption requestOption) {
    
            if(requestOption.iPostJsonStringCb !=null){
                requestOption.iPostJsonStringCb.onSuccess(resp,resp);
            }
        }
    }
    

    .
    .
    省缺接口

    public interface IPostJsonStringCb {
        void onSuccess(String str,String data);
        void onError(Response<String> response);
        void onStart(Request<String, ? extends Request> str);
        void onFinish();
    }
    

    .
    .
    抽象类

    public abstract class  AbsPostJsonStringCb implements IPostJsonStringCb{
    
        // 抽象类里面复写的方法后面作为 非必选方法。
        @Override
        public void onError(Response<String> response) {
    
        }
    
        @Override
        public void onStart(Request<String, ? extends Request> str) {
    
        }
    }
    
    

    使用示例

    findViewById(R.id.mTv).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    String url = ApiUrl.baseAdd + ApiUrl.login;
                    OkGoUtils.RequestOption requestOption = new OkGoUtils.RequestOption();
    
                    Map<String,String> map = new HashMap();
                    map.put("memberName", "zhangsan");
                    map.put("memberPass", "123456");
    
                    requestOption.context = MainActivity.this;
                    requestOption.url = url;
                    requestOption.params = map;
                    /**
                     * 如果不需要采用响应统一处理,requestOption.isNormalDeal = false;
                     * 如果想统一处理,则requestOption.isNormalDeal = true; 或者不传,默认就是true
                     */
                    requestOption.isNormalDeal = false;
                    requestOption.iPostJsonStringCb = new AbsPostJsonStringCb() {
                        @Override
                        public void onSuccess(String str, String data) {
                            FortuneLogUtils.d("success:"+str);
                            FortuneLogUtils.d("success:"+data);
                        }
    
                        @Override
                        public void onError(Response<String> response) {
                            super.onError(response);
                            FortuneLogUtils.d("onError:"+response.getException());
                        }
    
                        @Override
                        public void onFinish() {
                            FortuneLogUtils.d("onFinish:");
                        }
                    };
                    OkGoUtils.postJsonStringCallback(requestOption);
                }
            });
    

    代码都附上了,除了几个Log、Toast和Api类没附上而已。
    东西本来也不复杂,放上来,只是为了临时写个demo方便,所以成文。

    本文至此完,谢谢阅读。

    相关文章

      网友评论

        本文标题:基于OkGo(OkHttp)的统一请求响应小封装

        本文链接:https://www.haomeiwen.com/subject/gxoygftx.html