Android 浅谈Retrofit的封装
先了解Retrofit一般的使用步骤:
- 配置OkHttpClient,设置各种拦截器; - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183- private volatile static OkHttpClient okHttpClient; 
 private volatile static Retrofit retrofit;
 private static final int DEFAULT_CACHE_SIZE = 1024 * 1024 * 20;//默认缓存大小20M
 private static final int DEFAULT_MAX_AGE = 60 * 60;// 默认缓存时间单位
 private static final int DEFAULT_MAX_STALE_ONLINE = DEFAULT_MAX_AGE * 24;// 默认在线缓存时间
 private static final int DEFAULT_MAX_STALE_OFFLINE = DEFAULT_MAX_AGE * 24 * 7;// 默认离线缓存时间
 /**
 * 保存cookies拦截器
 */
 private static Interceptor SAVE_COOKIES_INTERCEPTOR = new Interceptor() {
 
 public Response intercept(Chain chain) throws IOException {
 SharedPreferences sharedPreferences = SuperRandyApplicationContext.context
 .getSharedPreferences("cookie_sp", Context.MODE_PRIVATE);
 Response originalResponse = chain.proceed(chain.request());
 // 如果cookie为空,保存cookie到sp文件
 if (CommonUtils.isNullOrEmpty(sharedPreferences.getString("cookie", ""))) {
 // 获取请求返回的cookies
 if (!CommonUtils.isNullOrEmpty(originalResponse.header("Set-Cookie")) &&
 !originalResponse.header("Set-Cookie").isEmpty()) {
 final StringBuffer cookieBuffer = new StringBuffer();
 Observable.from(originalResponse.headers("Set-Cookie"))
 .map(new Func1<String, String>() {
 
 public String call(String s) {
 String[] cookieArray = s.split(";");
 return cookieArray[0];
 }
 })
 .subscribe(new Action1<String>() {
 
 public void call(String s) {
 cookieBuffer.append(s).append(";");
 }
 });
 KLog.e("save_cookie", cookieBuffer.toString());
 // 保存cookies到sp文件
 SharedPreferences.Editor editor = sharedPreferences.edit();
 editor.putString("cookie", cookieBuffer.deleteCharAt(cookieBuffer.length() - 1).toString());
 editor.apply();
 }
 }
 return originalResponse;
 }
 };
 /**
 * 添加cookies拦截器
 */
 private static Interceptor ADD_COOKIES_INTERCEPTOR = new Interceptor() {
 
 public Response intercept(Chain chain) throws IOException {
 final Request.Builder builder = chain.request().newBuilder();
 SharedPreferences sharedPreferences = SuperRandyApplicationContext.context
 .getSharedPreferences("cookie_sp", Context.MODE_PRIVATE);
 Observable.just(sharedPreferences.getString("cookie", ""))
 .subscribe(new Action1<String>() {
 
 public void call(String s) {
 builder.addHeader("Cookie", s);
 }
 });
 KLog.e("add_cookie", sharedPreferences.getString("cookie", ""));
 return chain.proceed(builder.build());
 }
 };
 /**
 * request 拦截器定义
 */
 private static final Interceptor REQUEST_INTERCEPTOR = new Interceptor() {
 
 public Response intercept(Chain chain) throws IOException {
 Request request = chain.request();
 int maxStale = DEFAULT_MAX_STALE_ONLINE;
 //向服务期请求数据缓存1个小时
 CacheControl tempCacheControl = new CacheControl.Builder()
 // .onlyIfCached()
 .maxStale(5, TimeUnit.SECONDS)
 .build();
 request = request.newBuilder()
 .cacheControl(tempCacheControl)
 .build();
 return chain.proceed(request);
 }
 };
 /**
 * response 拦截器定义
 */
 private static final Interceptor RESPONSE_INTERCEPTOR = new Interceptor() {
 
 public Response intercept(Chain chain) throws IOException {
 //针对那些服务器不支持缓存策略的情况下,使用强制修改响应头,达到缓存的效果
 //响应拦截只不过是出于规范,向服务器发出请求,至于服务器搭不搭理我们我们不管他,我们在响应里面做手脚,有网没有情况下的缓存策略
 Request request = chain.request();
 Response originalResponse = chain.proceed(request);
 int maxAge;
 // 缓存的数据
 if (!NetworkUtils.isConnected(SuperRandyApplicationContext.context)) {
 maxAge = DEFAULT_MAX_STALE_OFFLINE;
 } else {
 maxAge = DEFAULT_MAX_STALE_ONLINE;
 }
 return originalResponse.newBuilder()
 .removeHeader("Pragma")// 清除头信息,因为服务器如果不支持,会返回一些干扰信息,不清除下面无法生效
 .removeHeader("Cache-Control")
 .header("Cache-Control", "public, max-age=" + maxAge)
 .build();
 }
 };
 /**
 * 打印返回的json数据拦截器
 */
 private static final Interceptor LOGGING_INTERCEPTOR = new Interceptor() {
 
 public Response intercept(Chain chain) throws IOException {
 final Request request = chain.request();
 final Response response = chain.proceed(request);
 final ResponseBody responseBody = response.body();
 final long contentLength = responseBody.contentLength();
 BufferedSource source = responseBody.source();
 source.request(Long.MAX_VALUE); // Buffer the entire body.
 Buffer buffer = source.buffer();
 Charset charset = Charset.forName("UTF-8");
 MediaType contentType = responseBody.contentType();
 if (contentType != null) {
 try {
 charset = contentType.charset(charset);
 } catch (UnsupportedCharsetException e) {
 KLog.e("");
 KLog.e("Couldn't decode the response body; charset is likely malformed.");
 return response;
 }
 }
 if (contentLength != 0) {
 long t1 = System.nanoTime();
 Log.i("OkHttp:", String.format("Sending %s request %s on %s%n%s", request.method(), request.url(), chain.connection(), request.headers()));
 long t2 = System.nanoTime();
 Log.i("OkHttp:", String.format("Received response for %s in %.1fms%n%s", response.request().url(), (t2 - t1) / 1e6d, response.headers()));
 KLog.v("--------------------------------------------开始打印返回数据----------------------------------------------------");
 KLog.json(buffer.clone().readString(charset));
 KLog.v("--------------------------------------------结束打印返回数据----------------------------------------------------");
 }
 return response;
 }
 };
 /**
 * 获取OkHttpClient实例
 *
 * @return OkHttpClient实例
 */
 private static OkHttpClient getOkHttpClient() {
 if (okHttpClient == null) {
 synchronized (OkHttpClient.class) {// 同步访问
 if (okHttpClient == null) {
 // 网络请求相关缓存
 File cacheFile = new File(SuperRandyApplicationContext.application.getCacheDir(), "responses");
 Cache cache = new Cache(cacheFile, DEFAULT_CACHE_SIZE);
 okHttpClient = new OkHttpClient.Builder()
 .cache(cache)
 // 添加相关拦截器
 .addInterceptor(SAVE_COOKIES_INTERCEPTOR)
 .addInterceptor(ADD_COOKIES_INTERCEPTOR)
 .addNetworkInterceptor(RESPONSE_INTERCEPTOR)
 .addInterceptor(REQUEST_INTERCEPTOR)
 .addInterceptor(LOGGING_INTERCEPTOR)
 .build();
 }
 }
 }
 return okHttpClient;
 }
- 配置Retrofit实例,主要是client; - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26- /** 
 * 获取OkHttpClient实例
 *
 * @return OkHttpClient实例
 */
 private static OkHttpClient getOkHttpClient() {
 if (okHttpClient == null) {
 synchronized (OkHttpClient.class) {// 同步访问
 if (okHttpClient == null) {
 // 网络请求相关缓存
 File cacheFile = new File(SuperRandyApplicationContext.application.getCacheDir(), "responses");
 Cache cache = new Cache(cacheFile, DEFAULT_CACHE_SIZE);
 okHttpClient = new OkHttpClient.Builder()
 .cache(cache)
 // 添加相关拦截器
 .addInterceptor(SAVE_COOKIES_INTERCEPTOR)
 .addInterceptor(ADD_COOKIES_INTERCEPTOR)
 .addNetworkInterceptor(RESPONSE_INTERCEPTOR)
 .addInterceptor(REQUEST_INTERCEPTOR)
 .addInterceptor(LOGGING_INTERCEPTOR)
 .build();
 }
 }
 }
 return okHttpClient;
 }
- 定义Service接口类,如 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- public interface User { 
 
 
 Observable<Response<BaseResponse<LoginResultBean>>> login( String username,
 String psw);
 
 Observable<Response<BaseResponse<Object>>> logout();
 
 
 Observable<Response<BaseResponse<Boolean>>> isRegistered( String mobile);
 
 }
- 获取Retrofit实例; - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21- /** 
 * 获取retrofit实例
 *
 * @param baseUrl baseURL
 * @return retrofit实例
 */
 public static Retrofit getRetrofit(String baseUrl) {
 if (retrofit == null) {
 synchronized (Retrofit.class) {
 if (retrofit == null) {
 retrofit = new Retrofit.Builder()
 .client(getOkHttpClient())
 .baseUrl(baseUrl)
 .addConverterFactory(GsonConverterFactory.create())
 .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
 .build();
 }
 }
 }
 return retrofit;
 }
- 创建Service,并访问接口 - 1 - getRetrofit("http://local.rainmonth.com").create(User.class).login("mobile", "password"); 
- 处理返回结果。 
封装所需要的功能
- 采用现在流行的链式结构进行创建;
- 提供一个接口形式的ApiService即可完成各种请求;
- 提供必要的回调函数处理返回结果;
- 提供通用的接收返回数据的容器;
- 支持多文件上传下载,并提供进度显示;(Download and upload)
- 可以动态配置;(Config)
- 良好的容错处理,能对返回结果进行统一处理和差异性处理;(网络错误,通用异常)(Exception and Error)
- Cookies持久化处理;(Cookie)
- 数据的缓存功能;(Cache,不同的缓存方式:内存,SD卡,数据库)
- 支持请求的取消,支持同步请求、支持异步请求;(方便调用get、post方法)
- 支持请求数据的拦截(方便后期调试)