这里关于android如何集成retrofit2.0就详细介绍了,相信网络上也有很多的例子。
首先retrofit关于请求体如何加入的话,这里使用注解就能解决大部分问题,而retrofit官网也给出了很多很好用的注解,只要在interface中声明就行。
主要使用分为以下例子:
①添加retrofit库依赖
②创建接受请求数据bean类
③创建用于请求的接口
④创建retrofit实例
⑤创建网络请求接口实例以及配置网络请求参数
⑥发送网络请求
⑦处理返回数据
主要从第四步讲起:
常规的retrofit实例创建是新建一个Builder()
比如:
Retrofit retrofit =new Retrofit.Builder()
.baseUrl(“www.XXXXXX”)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
这是常规创建实例,而我们知道,retrofit是基于okhttp的网络请求框架,所以我们封装的时候,可以写一个公有类,以下这是我的做法。
public class RetrofitHelper {
/** 连接超时:10秒 */
public static final int TIME_OUT_CONNECT = 10 * 1000;
/** 读数据超时:10秒 */
public static final int TIME_OUT_READ = 10 * 1000;
/** 转换日志输出格式 */
private static HttpLoggingInterceptor.Logger mLogger = new MyHttpLogger();
private static OkHttpClient mOkHttpClient;
//cookie存储
public static ConcurrentHashMap> cookieStore;
/**
* 获取带有json转换器的Retrofit对象,如果不需要json转换器请使用
* buildRetrofit(String baseUrl, boolean isNeedGsonConverter)方法获取
*
*/
public static Retrofit buildRetrofit(String baseUrl) {
return buildRetrofit(baseUrl, true);
}
/**
* 构建统一封装的Retrofit对象
*
* @param baseUrl
* @param isNeedGsonConverter 是否需要gson转换器
* @return Retrofit对象
*/
public static Retrofit buildRetrofit(String baseUrl, boolean isNeedGsonConverter) {
Retrofit.Builder builder = new Retrofit.Builder()
.client(getSingleOkHttpClient())
.baseUrl(baseUrl);
if (isNeedGsonConverter) {
builder.addConverterFactory(GsonConverterFactory.create());
}
return builder.build();
}
/**
* 获取OkHttpClient对象,用于需要定制OkHttpClient的情况。
* 该对象已经做了基本的封装,使用者可以在此基础上做进一步定制。
* 用法:
* Retrofit retrofit = RetrofitHelper.buildRetrofit("baseUrl");
* OkHttpClient okHttpClient = RetrofitHelper.getmOkHttpClient();
* ... // 对okHttpClient做一些个性化定制
* retrofit = retrofit.newBuilder().client(okHttpClient).build(); //重新设置定制好的client
* ... //继续后续操作
*
* 通常情况下不需要获取OkHttpClient对象,直接使用buildRetrofit()方法返回的Retrofit对象即可。
*
* @return
*/
public static OkHttpClient getmOkHttpClient() {
return buildClient();
}
/**
* 获取单例的okHttpClient对象
*
* @return
*/
private synchronized static OkHttpClient getSingleOkHttpClient() {
if (mOkHttpClient == null) {
mOkHttpClient = buildClient();
}
return mOkHttpClient;
}
/**
* 构建统一封装的OkHttpClient对象,
* 该对象增加了日志拦截器及连接超时等参数
*
* @return
*/
private static OkHttpClient buildClient() {
// 日志拦截器
HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(mLogger);
if(cookieStore==null){
cookieStore = new ConcurrentHashMap<>();
}
logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder builder = new OkHttpClient().newBuilder()
.connectTimeout(TIME_OUT_CONNECT, TimeUnit.MILLISECONDS)
.readTimeout(TIME_OUT_READ, TimeUnit.MILLISECONDS)
.cookieJar(new CookieJar() { //cookie拦截保存
@Override
public void saveFromResponse(HttpUrl url, List cookies) {
BaseActivity.setCookies(cookies);
Log.i("状态","Cookie保留成功");
Log.i("cooike为",BaseActivity.getCookies().toString());
}
@Override
public List loadForRequest(HttpUrl url) {
Log.i("cooike为",BaseActivity.getCookies().toString());
Log.i("状态","Cookie发送");
return BaseActivity.getCookies();
}
})
.addNetworkInterceptor(logInterceptor);
return builder.build();
}
/**
* 将http报文中的json字符串格式化并使用com.orhanobut.logger.Logger日志系统打印日志的类
*
*/
private static class MyHttpLogger implements HttpLoggingInterceptor.Logger {
StringBuilder mMessage = new StringBuilder();
@Override
public void log(String message) {
// 打印请求或者响应报文中的每一行都会调用此方法,所以用一个StringBuilder把它们串起来
// 以{}或者[]形式的说明是响应结果的json数据,需要进行格式化
boolean isJsonStr = (message.startsWith("{") && message.endsWith("}"))
|| (message.startsWith("[") && message.endsWith("]"));
if (isJsonStr) {
message = CommonUtils.formatJsonString(message);
}
mMessage.append(message.concat("\n"));
// 响应结束,打印整条日志
if (message.startsWith("<-- END HTTP")) {
Logger.d(mMessage.toString());
Logger.d("我是小尾巴");
mMessage.setLength(0);
}
}
}
}
接下来是对这个基础类的讲解,首先声明的是几个限制常量,用在okhttp中的超时设置中。接着是日志打印,我后面在发送请求的时候都会打印出来请求体与返回体,接着是一个cookie的存储,坑爹的是因为后台框架使用的是给WEB用的,登录状态用的是session来保存,后续请求也都是,所以在这里我将第一次登录获取到的session保存起来并在后面需要的时候就使用上。后面我在建立实例的时候,设置选择与不选择gson转换器的模式。
接下来讲的就是重点:
在new一个retrofit的builder的时候会设置client,这里我将client专门拿出来定制
/**
* 构建统一封装的OkHttpClient对象,
* 该对象增加了日志拦截器及连接超时等参数
*
* @return
*/
private static OkHttpClient buildClient() {
// 日志拦截器
HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(mLogger);
if(cookieStore==null){
cookieStore = new ConcurrentHashMap<>();
}
logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder builder = new OkHttpClient().newBuilder()
.connectTimeout(TIME_OUT_CONNECT, TimeUnit.MILLISECONDS)
.readTimeout(TIME_OUT_READ, TimeUnit.MILLISECONDS)
.cookieJar(new CookieJar() { //cookie拦截保存
@Override
public void saveFromResponse(HttpUrl url, List cookies) {
BaseActivity.setCookies(cookies);
Log.i("状态","Cookie保留成功");
Log.i("cooike为",BaseActivity.getCookies().toString());
}
@Override
public List loadForRequest(HttpUrl url) {
Log.i("cooike为",BaseActivity.getCookies().toString());
Log.i("状态","Cookie发送");
return BaseActivity.getCookies();
}
})
.addNetworkInterceptor(logInterceptor);
return builder.build();
}
在这上面我们设置了超时限制,以及cookie的保存以及cookie的发送。
以上是对okhttp的一些修饰
接下来我要讲的是关于retrofit返回状态码的拦截,主要操作的是第六步,发送网络请求的时候。
常规操作是这样的:
//发送异步请求
Call.enqueue(new Callback(){
//成功时回调
Public void onResponse(Call call,Response response){
Response.body().show();
}
//失败时回调
Public void onFailure(Call call,Throwable throwable) {
System.out.println(“连接失败”);
}
});
以上是我们的常规做法,直接使用已有的callback类
我实现的方法是使用自定义的Callback并接入callback接口类。
首先先定义自己的callback:
package com.b2bwings.framework.network;
import android.util.Log;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Created by xuweijie
* on 2018/7/16 0016.
*/
public final class MyCallBack implements Callback {
/** 公共事务处理器 */
private static ICommonProcessor processor;
/** 网络请求回调接口 */
private LoadDataCallBack loadDataCallBack;
public MyCallBack(LoadDataCallBack loadDataCallBack) {
this.loadDataCallBack = loadDataCallBack;
}
@Override
public void onFailure(Call call, Throwable t) {
// 这里可以对错误做统一的处理,目前只输出错误日志,子类可以重写此方法作进一步处理
String url = call.request().url().toString();
}
@Override
public void onResponse(Call call, Response response) {
switch (response.code()) {
case 401:
// 401 代表登录失效(登录session失效)
if (processor != null) {
Log.d("状态","统一处理401错误");
processor.process401();
} else {
Log.w("状态","401错误,未设置公共处理器");
}
return;
//暂未设置错误码拦截器
default:
break;
}
loadDataCallBack.onSuccess(response);
}
/**
* 设置公共处理器
*
* @param iCommonProcessor
*/
public static void setCommonProcessor(ICommonProcessor iCommonProcessor) {
processor = iCommonProcessor;
}
}
以及拦截接口
/**
* Created by xuweijie
* on 2018/7/13 0013.
*/
public interface ICommonProcessor {
/**
* 处理401错误,即登录失效
*/
void process401();
}
//加载数据回调接口
public interface LoadDataCallBack {
/**
* 加载数据成功
*
* @param response 返回的数据
*/
void onSuccess(Response response);
/**
* 加载数据失败
*
* @param throwable 错误信息
*/
void onError(Throwable throwable);
}
其中在onResponse响应中,处理完拦截器之后就会回调onSuccedd回调。
以上是进行了状态码401的拦截。
最后要注意的是,必须在使用到拦截器的地方的进行设置
即:
MyCallBack.setCommonProcessor(this);
以上就是我对retrofit的一些封装,实现了返回提中cookie的拦截,以及返回体状态码的统一处理。
如果大家有什么疑问或者意见,欢迎批评指正