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输出