超级实用!!!对于retrofit 2.0+okhttp 3的一些封装

最近几天都在看retrofit和okhttp这个开源网络库组合,现在来分享和大家一下。
首先引入依赖
如下:

    compile 'com.squareup.okhttp3:okhttp:3.2.0'
    compile 'com.squareup.retrofit2:retrofit:2.0.0'
    compile 'com.squareup.retrofit2:converter-gson:2.0.0'
    compile 'com.google.code.gson:gson:2.6.2'
    compile 'com.squareup.okhttp3:logging-interceptor:3.4.0'

首先来看

  1. 1.

okhttp的Builder的 配置模式

          OkHttpClient.Builder builder = new OkHttpClient.Builder();
            /**
             *设置缓存
             */
            File cacheFile = new File(MyApplication.getInstance().getExternalCacheDir(), "AppCache");
            Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);
            Interceptor cacheInterceptor = new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request request = chain.request();
                    if (!NetworkUtils.isNetworkAvailable(MyApplication.getInstance())) {
                        request = request.newBuilder()
                                .cacheControl(CacheControl.FORCE_CACHE)
                                .build();
                    }
                    Response response = chain.proceed(request);
                    if (NetworkUtils.isNetworkAvailable(MyApplication.getInstance())) {
                        int maxAge = 0;
                        // 有网络时 设置缓存超时时间0个小时
                        response.newBuilder()
                                .header("Cache-Control", "public, max-age=" + maxAge)
                                .removeHeader("app")// 清除头信息,因为服务器如果不支持,会返回一些干扰信息,不清除下面无法生效
                                .build();
                    } else {
                        response.newBuilder()
                                .header("Cache-Control", "public, only-if-cached, max-stale=" + "60 * 60 * 24 * 7")
                                .removeHeader("app")
                                .build();
                        ActivityUtils.toast(R.string.no_net_connect_txt);
                    }
                    return response;
                }
            };
            builder.cache(cache).addInterceptor(cacheInterceptor);
            /**
             *  公共参数
             */
            Interceptor addQueryParameterInterceptor = new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request originalRequest = chain.request();
                    Request request = null;
                    HttpUrl modifiedUrl = originalRequest.url().newBuilder()
                            .addQueryParameter("参数", "")
                            .build();
                    request = originalRequest.newBuilder().url(modifiedUrl).build();
                    return chain.proceed(request);
                }
            };
            builder.addInterceptor(addQueryParameterInterceptor);

            /**
             * 设置头
             */

            /**
             * Log信息拦截器
             */
            if (BuildConfig.DEBUG) {
                // Log信息拦截器
                HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
                loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                //设置 Debug Log 模式
                builder.addInterceptor(loggingInterceptor);
            }
            /**
             * 设置cookie
             */

            /**
             * 设置超时和重连
             */
            //设置超时
            builder.connectTimeout(10, TimeUnit.SECONDS);
            builder.readTimeout(10, TimeUnit.SECONDS);
            builder.writeTimeout(10, TimeUnit.SECONDS);
            builder.retryOnConnectionFailure(true);//错误重连

            OkHttpClient okHttpClient = builder.build();

然后是Retrofit配置

public static Retrofit retrofit = null;

 public static Retrofit retrofit() {
        if (retrofit == null) {
        ......//okhttp的配置放在这
        retrofit = new Retrofit.Builder()
                    .baseUrl(ApiUrl.getHeadUrl())
                    .client(okHttpClient)
                    .addConverterFactory(JsonConverterFactory.create())//转换器

                    .build();
        }
        return retrofit;
}

这里注意一点 JsonConverterFactory.create()这个是自定义的转换器,如果不需要刻意直接使用GsonConverterFactory.create()

当然在日常开发中系统给的转换器并不能给我们带来方便,所以我们必须

自定义转换器

public class JsonConverterFactory extends Converter.Factory {

    public static JsonConverterFactory create() {
        return new JsonConverterFactory();
    }


    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {
        return new JsonResponseBodyConverter<>(type);//响应
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type,
                                                          Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {

        return new JsonRequestBodyConverter<>();//请求
    }
}

接下来是请求响应

public class JsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
    private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");

    @Override
    public RequestBody convert(T value) throws IOException {
        return RequestBody.create(MEDIA_TYPE, value.toString());
    }

}

下面最重要的来了。我个人认为这也是最核心的一个点,因为我的写法上的错误,导致我被这个问题困了很久。

public class JsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {

    private final Type type;

    public JsonResponseBodyConverter(Type type) {
        this.type = type;
    }

    /**
     * 转换
     *
     * @param responseBody
     * @return
     * @throws IOException
     */
    @Override
    public T convert(ResponseBody responseBody) throws IOException {
        BufferedSource bufferedSource = Okio.buffer(responseBody.source());
        String tempStr = bufferedSource.readUtf8();
        bufferedSource.close();
        JSONObject jsonObject = null;
        T t = null;
        try {
            jsonObject = new JSONObject(tempStr);
            t = GsonHelper.getDeserializer().fromJson(jsonObject.getString("data"), type);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return t;

    }
}

需要注意的是,**为了封装我老是想着把需要解析的类传入进去,其实不然,这里的这个T,就代表着这个类,结果输出t就可以了。
下面是我的错误代码**:

public T convert(ResponseBody responseBody) throws IOException {
        BufferedSource bufferedSource = Okio.buffer(responseBody.source());
        String tempStr = bufferedSource.readUtf8();
        bufferedSource.close();
        JSONObject jo = null;
        Object jsonObject = null;

        try {
            jo = new JSONObject(tempStr);
            jsonObject = new JSONObject(jo.getString("data"));
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return (T) jsonObject;
    }

看到了么,这里返回的数据类型被我弄成了JSONObject,当解析的数据是JSONObject是正确的,而一旦解析的数据是JSONArray时,就不正确了。引以为戒!!!

再来看我封装的

Call回调

public class BaseRequest<T> {
    private Call<T> mCall;

    public BaseRequest(Call call) {
        mCall = call;
    }

    //异步请求
    public void handleResponse(final ResponseListener listener) {
        mCall.enqueue(new Callback<T>() {
            @Override
            public void onResponse(Call<T> call, Response<T> response) {
                if (response.raw().code() == 200) {//200是服务器有合理响应
                    if (response.isSuccessful()) {
                        listener.onSuccess(response.body());
                    }
                } else {
                    //失败响应
                    onFailure(call, new RuntimeException("response error,detail = " + response.raw().toString()));
                }
            }

            @Override
            public void onFailure(Call<T> call, Throwable t) {
                if (t instanceof SocketTimeoutException) {
                    ActivityUtils.toast("连接超时!");
                } else if (t instanceof ConnectException) {
                    ActivityUtils.toast("网络出错");
                }
                listener.onFail();
            }
        });
    }

    // 取消
    public void cancel() {
        mCall.cancel();
    }


    public interface ResponseListener<T> {

        void onSuccess(T t);

        void onFail();
    }
}

然后

调取方法

new BaseRequest<Result>(AppClient.retrofit().create(ResultService.class)
                .getResult(...)).handleResponse(baseResultResponseListener);


BaseRequest.ResponseListener<Result> baseResultResponseListener = new BaseRequest.ResponseListener<Result>() {

        @Override
        public void onSuccess(Result result) {

        }

        @Override
        public void onFail() {

        }
    };

这样写好之后,你可以看看,是不是调取就方便些了呢。欢迎各位指正,谢谢

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值