Retrofit2.0(三)封装:如超时设置,加请求头,加公共请求参数,加拦截器等

Retrofit2.0(三)封装:如超时设置,加请求头,加公共请求参数,加拦截器等


Retrofit2.0基本使用参考:
Retrofit2.0(一)retrofit基本使用讲解和Converter转换器使用


通过 OkHttpClient.Builder 实现相关设置:

 OkHttpClient.Builder builder = new OkHttpClient().newBuilder();

1 超时设置

private static final int CONNECT_TIMEOUT = 10;
private static final int READ_TIMEOUT = 20;
private static final int WRITE_TIMEOUT = 20;

builder.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS); // 连接超时时间阈值
builder.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS);   // 数据获取时间阈值
builder.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS);  // 写数据超时时间阈值

2 错误重连

builder.retryOnConnectionFailure(true);              //错误重连

拦截器知识:
可以:
设置通用Header
设置通用请求参数
拦截响应
统一输出日志
实现缓存

分为 网络拦截器 和 应用拦截器
应用拦截器:
1 不关心是否重定向或者失败重连
2 只调用一次
3 只考虑应用的初始意识,不考虑Header之类的
网络拦截器:
1 可以操作重定向或者失败重连的返回值
2 如果取缓存中的数据 则不执行
3 可以观察所有网络传输的数据


3 加公共参数
创建 公共参数拦截器:

import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

public class AddQueryParameterInterceptor implements Interceptor{
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();
        Request request;
        HttpUrl modifiedUrl = originalRequest.url().newBuilder()
                // Provide your custom parameter here
                .addQueryParameter("token", GlobalVariable.Token)
                .addQueryParameter("version", GlobalVariable.VERSION)
                .addQueryParameter("deviceOs", GlobalVariable.DEVICE_OS)
                .addQueryParameter("lang", GlobalVariable.LANG)
                .addQueryParameter("deviceCode", GlobalVariable.DEVICE_CODE)
                .build();
        request = originalRequest.newBuilder().url(modifiedUrl).build();
        return chain.proceed(request);
    }
}

这种方式是 通过在URL上 加的公共请求参数,一般是通过请求头方式加

若有些请求不用或者不用全部公共请求参数
则那些不用的 传空值即可


4 加请求头:

Request originalRequest = chain.request();
                Request.Builder builder = originalRequest.newBuilder();
                builder.header("appid", "123124151616");
                builder.header("appkey", "xxxxxxxxx");
                builder.header("signature", "xxxxxxxxxxx");

                Request.Builder requestBuilder =builder.method(originalRequest.method(), originalRequest.body());
                Request request = requestBuilder.build();
                return chain.proceed(request);

5 设置缓存机制: 待处理


6 加Log信息拦截
用于获取 请求 响应的 数据

compile 'com.squareup.okhttp3:logging-interceptor:3.1.2'
// Debug时才设置Log拦截器,才可以看到
        if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(

            );
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder.addInterceptor(interceptor);
        }

BuildConfig 导入的是包下的BuildConfig

若有的手机显示不了Log
解决1 : 看看是否手机设置了不打开该Log日志设置,可以百度查询怎么打开。
解决2 :

 // Debug时才设置Log拦截器,才可以看到
    if (BuildConfig.DEBUG) {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(
                // 添加json数据拦截
            new HttpLoggingInterceptor.Logger() {
                @Override
                public void log(String message) {
                // Log.i("收到响应:", message);
                    if (TextUtils.isEmpty(message)) return;
                    //如果收到响应是json才打印
                    String s = message.substring(0, 1);
                    if ("{".equals(s) || "[".equals(s)) {
                        Log.i("收到响应:", message);
                    }
                }
            }
        );
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        builder.addInterceptor(interceptor);
    }

网络拦截器则 为 addNetworkInterceptor()


7 OKHttp携带 cookie


使用:

// 创建okhttpClient 将builder建立
OkHttpClient okHttpClient = builder.build();
 Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl) //   baseUrl 中的路径(baseUrl)必须以 / 结束
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                 .client(okHttpClient)
                .build();

问题:
1 java.lang.NoClassDefFoundError: Failed resolution of: Lokhttp3/internal/Platform;
解析:OKHttp版本和com.squareup.okhttp3:logging-interceptor版本不一致


封装:


import android.text.TextUtils;
import android.util.Log;
import com.biniu.bottomnavigationbardemo.BuildConfig;
import com.biniu.bottomnavigationbardemo.Net.Interceptor.AddQueryParameterInterceptor;
import com.biniu.bottomnavigationbardemo.Utils.GlobalVariable;
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import java.util.concurrent.TimeUnit;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class RetrofitFactory {
    private APIService apiService;
    private static final int CONNECT_TIMEOUT = 10;
    private static final int READ_TIMEOUT = 20;
    private static final int WRITE_TIMEOUT = 20;

    //声明RetrofitFactory对象
    private volatile static RetrofitFactory retrofitFactory;

    // 将构造函数改成private类型 避免外部创建对象 实现单例思想
    private RetrofitFactory() {

        //OKHttp进行超时设置
        OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
        builder.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS); // 连接超时时间阈值
        builder.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS);   // 数据获取时间阈值
        builder.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS);  // 写数据超时时间阈值

        builder.retryOnConnectionFailure(true);              //错误重连

        // Debug时才设置Log拦截器,才可以看到
        if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(
                    // 添加json数据拦截
                    new HttpLoggingInterceptor.Logger() {
                        @Override
                        public void log(String message) {
                            if (TextUtils.isEmpty(message)) return;
                            //如果收到响应是json才打印
                            String s = message.substring(0, 1);
                            if ("{".equals(s) || "[".equals(s)) {
                                Log.i("收到响应:", message);
                            }
                        }
                    }
            );
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder.addInterceptor(interceptor);
        }

        // 设置 公共请求参数 如 token 设备版本 软件版本 语言
        builder.addInterceptor(new AddQueryParameterInterceptor());

        // 设置请求头 也是通过拦截器

        // 创建okhttpClient 将builder建立
        OkHttpClient okHttpClient = builder.build();

        // 2 创建 Retrofit实例
        String baseUrl = GlobalVariable.SERVERDOMAIN;

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)         //  *** baseUrl 中的路径(baseUrl)必须以 / 结束 ***
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(okHttpClient)
                .build();

        // 3 创建接口的代理对象
        apiService = retrofit.create(APIService.class);
    }

    // 向外部提供一个 该类的对象接口
    public static RetrofitFactory getInstance(){
        if(retrofitFactory == null){
        synchronized(RetrofitFactory.class){
                if(retrofitFactory == null){
                    retrofitFactory = new RetrofitFactory();
                }
            }
        }
        return retrofitFactory;
    }

    // 封装rxjava
    public void doHttpRequest(Observable pObservable, Observer observer) {
        Observable observable = pObservable ;
        observable.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);                       // unchecked generify
    }

    public APIService getApiService(){
        return apiService;
    }

}

待完善:
1 移除请求
call.cancel();
2 加上提供 重写 baseUrl的接口
3 加上网络无连接 有连接无数据的封装
这里是每个网络请求都进行这个判断 然后在传入context 工具类中进行Toast输出

猜你喜欢

转载自blog.csdn.net/weixin_37577039/article/details/79495797