优雅封装Retrofit+RxJava联网的统一管理类

Retrofit的简单用法在上一篇文章 分分钟使用Retrofit+Rxjava实现网络请求,已经做过介绍了,今天就不赘述了。
今天主要分享一下如何结合Rxjava,封装一个RetrofitManager管理类,统一管理联网操作。
《一》让我们先来看看封装后的用法:

  RetrofitManager.getInstance().getRequestService().getWeather("北京").compose(RxSchedulers.io_main()).subscribeWith(new DisposableObserver() {@Overridepublic void onNext(Object result) {                                Log.e("TAG", "result=" + result.toString());}@Overridepublic void onError(Throwable e) {Log.e("TAG", "onError=" + e.getMessage());}@Overridepublic void onComplete() {Log.e("TAG", "onComplete");}});封装后的用法大家看到了,链式调用,一步到位,非常简洁明了。接下来我就带着大家一步步封装一个RetrofitManager。 

《二》封装Retrofit+Rxjava的管理类RetrofitManager
(1)在app的build.gradle下配置Retrofit和Rxjava相关的依赖包
   //rxandroidimplementation 'io.reactivex.rxjava2:rxandroid:2.0.2'//rxjavaimplementation 'io.reactivex.rxjava2:rxjava:2.1.10'//retrofitimplementation "com.squareup.retrofit2:retrofit:2.4.0"//gsonConverterimplementation "com.squareup.retrofit2:converter-gson:2.4.0"//rxjavaAdapterimplementation "com.squareup.retrofit2:adapter-rxjava2:2.4.0"//retrofit log打印implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1'
(小提醒: Android Studio3.0之后的依赖,由compile变成了implementation。)

(2)①新建RetrofitManager类,提供单例

public class RetrofitManager {/*** 获取单例*/private static RetrofitManager mInstance;public static RetrofitManager getInstance() {if (mInstance == null) {synchronized (RetrofitManager.class) {if (mInstance == null) {mInstance = new RetrofitManager();}}}return mInstance;}
}

②配置OkHttp,构建Retrofit对象

  private static final long DEFAULT_TIMEOUT = 60L;public Retrofit getRetrofit() {if (retrofit == null) {synchronized (RetrofitManager.class) {if (retrofit == null) {OkHttpClient mClient = new OkHttpClient.Builder()//添加公共查询参数//.addInterceptor(new CommonQueryParamsInterceptor())//.addInterceptor(new MutiBaseUrlInterceptor())//添加header.addInterceptor(new HeaderInterceptor()).addInterceptor(new LoggingInterceptor())//添加请求拦截(可以在此处打印请求信息和响应信息).connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).build();retrofit = new Retrofit.Builder().baseUrl(BASE_URL)//基础URL 建议以 / 结尾.addConverterFactory(GsonConverterFactory.create())//设置 Json 转换器.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//RxJava 适配器.client(mClient).build();}}}return retrofit;}
③通过代理的方式,创建ApiServe接口的实例。
 public ApiService getRequestService() {return getRetrofit().create(ApiService.class);}
ApiService是一个自己定义的interface,所有的网络请求接口的配置,都在此接口内完成。网络请求URL的配置可以参考 Retrofit请求参数的配置
interface ApiService {//获取北京的天气信息
//    "https://www.sojson.com/open/api/weather/json.shtml?city=" + "北京"@GET("weather/json.shtml")Observable getWeather(@Query("city")String city);//上传文件@POST("upload/")Observable uploadFile(@Body RequestBody body);
}④Header的配置 

   /*** 添加请求头需要携带的参数*/public class HeaderInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();Request requestBuilder = request.newBuilder().addHeader("Connection", HEADER_CONNECTION).addHeader("token", "token-value").method(request.method(), request.body()).build();return chain.proceed(requestBuilder);}}
⑤Retrofit的log日志打印
/*** log打印:参考:http://blog.csdn.net/csdn_lqr/article/details/61420753*/public class LoggingInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {//这个chain里面包含了request和response,所以你要什么都可以从这里拿Request request = chain.request();long t1 = System.nanoTime();//请求发起的时间String method = request.method();JSONObject jsonObject = new JSONObject();if ("POST".equals(method) || "PUT".equals(method)) {if (request.body() instanceof FormBody) {FormBody body = (FormBody) request.body();if (body != null) {for (int i = 0; i < body.size(); i++) {try {jsonObject.put(body.name(i), body.encodedValue(i));} catch (JSONException e) {e.printStackTrace();}}}Log.e("request", String.format("发送请求 %s on %s  %nRequestParams:%s%nMethod:%s",request.url(), chain.connection(), jsonObject.toString(), request.method()));} else {Buffer buffer = new Buffer();RequestBody requestBody = request.body();if (requestBody != null) {request.body().writeTo(buffer);String body = buffer.readUtf8();Log.e("request", String.format("发送请求 %s on %s  %nRequestParams:%s%nMethod:%s",request.url(), chain.connection(), body, request.method()));}}} else {Log.e("request", String.format("发送请求 %s on %s%nMethod:%s",request.url(), chain.connection(), request.method()));}Response response = chain.proceed(request);long t2 = System.nanoTime();//收到响应的时间ResponseBody responseBody = response.peekBody(1024 * 1024);Log.e("request",String.format("Retrofit接收响应: %s %n返回json:【%s】 %n耗时:%.1fms",response.request().url(),responseBody.string(),(t2 - t1) / 1e6d));return response;}}

看一下日志打印的效果,有了日志打印,我们就能轻松的调试每个网络请求了。


《三》OkHttp的拦截器Interceptor
无论是上面添加header,还是处理log日志打印,或是设置缓存,配置一些公共请求参数等等,都是通过添加拦截器addInterceptor()来实现的,所以拦截器有多重要,就不用我多说了啦~

先举个简单的栗子,了解一下拦截器是个什么东西?
**官方介绍**:拦截器是一种能够监控,重写,重试调用的**强大机制**。拦截发出的请求和传入的响应的日志.
**打个比方**:镖局押着一箱元宝走过一个山间小路,突然从山上下来一群山贼拦住了镖局的去路,将镖局身上值钱的东西搜刮干净后将其放行。其中山贼相当于拦截器,镖局相当于一个正在执行任务的网络请求,请求中的参数就是镖局携带的元宝。拦截器可以将网络请求携带的参数进行修改验证,然后放行。这里面其实设计了AOP编程的思想( 面向切面编程)。


详细了解可参考:
Okhttp拦截器

Interceptors拦截器

手把手带你深入剖析Retrofit2.0源码



附上RetrofitManager的完整代码(包括Retrofit文件的上传):
package com.zongxueguan.naochanle_android.net.retrofit;import com.zongxueguan.naochanle_android.global.API;
import com.zongxueguan.naochanle_android.retrofitrx.ApiService;
import com.zongxueguan.naochanle_android.util.UserConstants;
import com.zxg.framework.library.common.log.Elog;import org.json.JSONException;
import org.json.JSONObject;import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;import okhttp3.CacheControl;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;
import okio.Buffer;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;/*** Created by JoJo on 2018/4/24.* wechat:18510829974* description:*/
public class RetrofitManager {/*** 请求接口实例对象*/private static RetrofitManager mInstance;private static final long DEFAULT_TIMEOUT = 60L;private Retrofit retrofit = null;//请求头信息private final String HEADER_CONNECTION = "keep-alive";public static RetrofitManager getInstance() {if (mInstance == null) {synchronized (RetrofitManager.class) {if (mInstance == null) {mInstance = new RetrofitManager();}}}return mInstance;}public Retrofit getRetrofit() {if (retrofit == null) {synchronized (RetrofitManager.class) {if (retrofit == null) {OkHttpClient mClient = new OkHttpClient.Builder()//添加公告查询参数
//                          .addInterceptor(new CommonQueryParamsInterceptor())
//                          .addInterceptor(new MutiBaseUrlInterceptor()).addInterceptor(new HeaderInterceptor()).addInterceptor(new LoggingInterceptor())//添加请求拦截(可以在此处打印请求信息和响应信息).connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).build();retrofit = new Retrofit.Builder().baseUrl(API.getInstance().BASE_API_URL)//基础URL 建议以 / 结尾.addConverterFactory(GsonConverterFactory.create())//设置 Json 转换器.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//RxJava 适配器.client(mClient).build();}}}return retrofit;}public ApiService getRequestService() {return getRetrofit().create(ApiService.class);}/*** 设置公共查询参数*/public class CommonQueryParamsInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();HttpUrl url = request.url().newBuilder().addQueryParameter("paramsA", "a").addQueryParameter("paramsB", "b").build();return chain.proceed(request.newBuilder().url(url).build());}}/*** 添加请求头需要携带的参数*/public class HeaderInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();Request requestBuilder = request.newBuilder().addHeader("Connection", HEADER_CONNECTION).addHeader("token", "token-value").method(request.method(), request.body()).build();return chain.proceed(requestBuilder);}}/*** 设置缓存*/public class CacheInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build();Response response = chain.proceed(request);int maxAge = 0;// 有网络时 设置缓存超时时间0个小时 ,意思就是不读取缓存数据,只对get有用,post没有缓冲response.newBuilder().header("Cache-Control", "public, max-age=" + maxAge).removeHeader("Retrofit")// 清除头信息,因为服务器如果不支持,会返回一些干扰信息,不清除下面无法生效.build();// 无网络时,设置超时为4周  只对get有用,post没有缓冲int maxStale = 60 * 60 * 24 * 28;response.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale).removeHeader("nyn").build();return response;}}/*** log打印:http://blog.csdn.net/csdn_lqr/article/details/61420753*/public class LoggingInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {//这个chain里面包含了request和response,所以你要什么都可以从这里拿Request request = chain.request();long t1 = System.nanoTime();//请求发起的时间String method = request.method();JSONObject jsonObject = new JSONObject();if ("POST".equals(method) || "PUT".equals(method)) {if (request.body() instanceof FormBody) {FormBody body = (FormBody) request.body();if (body != null) {for (int i = 0; i < body.size(); i++) {try {jsonObject.put(body.name(i), body.encodedValue(i));} catch (JSONException e) {e.printStackTrace();}}}Elog.e("request", String.format("发送请求 %s on %s  %nRequestParams:%s%nMethod:%s",request.url(), chain.connection(), jsonObject.toString(), request.method()));} else {Buffer buffer = new Buffer();RequestBody requestBody = request.body();if (requestBody != null) {request.body().writeTo(buffer);String body = buffer.readUtf8();Elog.e("request", String.format("发送请求 %s on %s  %nRequestParams:%s%nMethod:%s",request.url(), chain.connection(), body, request.method()));}}} else {Elog.e("request", String.format("发送请求 %s on %s%nMethod:%s",request.url(), chain.connection(), request.method()));}Response response = chain.proceed(request);long t2 = System.nanoTime();//收到响应的时间ResponseBody responseBody = response.peekBody(1024 * 1024);Elog.e("request",String.format("Retrofit接收响应: %s %n返回json:【%s】 %n耗时:%.1fms",response.request().url(),responseBody.string(),(t2 - t1) / 1e6d));return response;}}/*** 打印log日志:该拦截器用于记录应用中的网络请求的信息*/private HttpLoggingInterceptor getHttpLogingInterceptor() {HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {@Overridepublic void log(String message) {//包含所有的请求信息//如果收到响应是json才打印if ("{".equals(message) || "[".equals(message)) {Log.d("TAG", "收到响应: " + message);}Log.d("TAG", "message=" + message);}});httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);return httpLoggingInterceptor;}private String BASE_URL_OTHER = "http://wthrcdn.etouch.cn/";/*** 添加可以处理多个Baseurl的拦截器:http://blog.csdn.net/qq_36707431/article/details/77680252* Retrofit(OKHttp)多BaseUrl情况下url实时自动替换完美解决方法:https://www.2cto.com/kf/201708/663977.html//     http://wthrcdn.etouch.cn/weather_mini?city=北京
//    @Headers({"url_name:other"})
//    @GET("weather_mini")
//    Observable getMessage(@Query("city") String city);*/private class MutiBaseUrlInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {//获取requestRequest request = chain.request();//从request中获取原有的HttpUrl实例oldHttpUrlHttpUrl oldHttpUrl = request.url();//获取request的创建者builderRequest.Builder builder = request.newBuilder();//从request中获取headers,通过给定的键url_nameList headerValues = request.headers("url_name");if (headerValues != null && headerValues.size() > 0) {//如果有这个header,先将配置的header删除,因此header仅用作app和okhttp之间使用builder.removeHeader("url_name");//匹配获得新的BaseUrlString headerValue = headerValues.get(0);HttpUrl newBaseUrl = null;if ("other".equals(headerValue)) {newBaseUrl = HttpUrl.parse(BASE_URL_OTHER);
//                } else if ("other".equals(headerValue)) {
//                    newBaseUrl = HttpUrl.parse(BASE_URL_PAY);} else {newBaseUrl = oldHttpUrl;}//在oldHttpUrl的基础上重建新的HttpUrl,修改需要修改的url部分HttpUrl newFullUrl = oldHttpUrl.newBuilder().scheme("http")//更换网络协议,根据实际情况更换成https或者http.host(newBaseUrl.host())//更换主机名.port(newBaseUrl.port())//更换端口.removePathSegment(0)//移除第一个参数v1.build();//重建这个request,通过builder.url(newFullUrl).build();// 然后返回一个response至此结束修改Elog.e("Url", "intercept: " + newFullUrl.toString());return chain.proceed(builder.url(newFullUrl).build());}return chain.proceed(request);}}/*** Retrofit上传文件** @param mImagePath* @return*/public RequestBody getUploadFileRequestBody(String mImagePath) {File file = new File(mImagePath);//构建bodyRequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file)).build();return requestBody;}
}











































本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章