Android开发之路

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

2018-09-11  本文已影响1090人  阿敏其人

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

特点

小封装开始

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方便,所以成文。

本文至此完,谢谢阅读。

上一篇下一篇

猜你喜欢

热点阅读