android中Retrofit2.0的封装:设计到请求前后的操作,比如添加请求头,拦截请求头,拦截返回体等
这里关于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的拦截,以及返回体状态码的统一处理。
如果大家有什么疑问或者意见,欢迎批评指正
更多相关文章
- Android(安卓)关于引用jackson的jar包混淆报错或打包后运行报错
- Android内存管理与泄漏场景分析
- 写给VR手游开发小白的教程:(五)Cardboard插件与Android之间的通信交
- Android事件学习总结
- Android(Java)中的Object
- Android强、软、弱、虚引用
- Andriod的Http请求获取Cookie信息并同步保存,使第二次不用登录也
- Android的轻量级数据库sqlite、以及文件存取byte数组
- android binder机制之——(我是binder实例)