Android基于Retrofit2.0+RxJava 封裝的超好用的RetrofitClient工具類(完美結合RxJava)(六)

? ? ? 簡書 :天天大保建

? ? ? 原文地址:

? ? ??http://www.lxweimin.com/p/29c2a9ac5abf


基于Retrofit2.0 封裝的超好用的RetrofitClient

結尾的github的2.x分支項目已經做對Rxjava2做了支持,可自行下載。

RetrofitClient

基于Retrofit2.0封裝的RetrofitClient.

避免重復創建Retrofit實列.

調用方便簡潔.

無需重復設置屬性的步驟.

可固定配置 Host 也可動態配置Url、請求頭、參數等.

支持文件下載和上傳.

支持json形式提交.

支持擴展APIService

統一處理無網絡情況,和支持加載進度

結合RxJava

支持緩存機制

優化取消

使用原生的Retrofit請求網絡,熟悉的朋友必定了解,在某個ApiServie方法多時 Retrofit設置就顯得有點累贅,今天給大家帶來對Retrofit的基本封裝。這次對Retrofit進階篇,本次封裝已加入RxJava,請在閱讀下文前請先了解RXJAVA和本人寫的Retrofit系列文章,

Retrofit 2.0

超能實踐,完美支持Https傳輸

Retrofit2.0

完美同步Cookie實現免登錄

Retrofit 2.0 超能實踐,輕松實現多文件/圖片上傳

基本步驟:

構建Retrofit的接口service.

構建基礎攔截器 Interceptor.

構建Cookie管理工具CookieManger.

構建 單列RetrofitClient客戶端.

RetrofitClient的使用.

ApiService

請求網絡的API接口類,這里你可以增加你需要的請求接口,也可復用已經實現的幾個方法。

/**

* Created by Tamic on 2016-07-08.

*/

public interface ApiService {

public static final String Base_URL = "http://ip.taobao.com/";

/**

*普通寫法

*/

@GET("service/getIpInfo.php/")

Observable getData(@Query("ip") String ip);

@GET("{url}")

Observable executeGet(

@Path("url") String url,

@QueryMap Map maps);

@POST("{url}")

Observable executePost(

@Path("url") String url,

@FieldMap Map maps);

@Multipart

@POST("{url}")

Observable upLoadFile(

@Path("url") String url,

@Part("image\\"; filename=\\"image.jpg") RequestBody avatar);

@POST("{url}")

Call uploadFiles(

@Url("url") String url,

@Part("filename") String description,

@PartMap()? Map maps);

}

上面新增了幾個常用的請求方法

第一個只是普通寫法的列子, url ,請求頭,參數都是寫死的。 不建議這么做

第二,三個分別是Get 和POST請求,method Url, headers, body參數都可以動態外部傳入。

四 五是單文件/圖片和多文件/圖片上傳

構建基礎攔截器

用來設置基礎header,這里是通過MAP鍵值對來構建,將heder加入到Request中。

/**

* BaseInterceptor,use set okhttp call header

* Created by Tamic on 2016-06-30.

*/

public class BaseInterceptor implements Interceptor{

private Map headers;

public BaseInterceptor(Map headers) {

this.headers = headers;

}

@Override

public Response intercept(Chain chain) throws? ? IOException {

Request.Builder builder = chain.request()

.newBuilder();

if (headers != null && headers.size() > 0) {

Set keys = headers.keySet();

for (String headerKey : keys) {

builder.addHeader(headerKey,? headers.get(headerKey)).build();

}

}

return chain.proceed(builder.build());

}

}

構建Cookie管理者

用來管理cookie, 儲存cookie的store這里不再重復說明,具體列子請見:

public class NovateCookieManger implements CookieJar {

private static final String TAG = "NovateCookieManger";

private static Context mContext;

private static PersistentCookieStore cookieStore;

/**

* Mandatory constructor for the NovateCookieManger

*/

public NovateCookieManger(Context context) {

mContext = context;

if (cookieStore == null) {

cookieStore = new PersistentCookieStore(mContext);

}

}

@Override

public void saveFromResponse(HttpUrl url, List cookies) {

if (cookies != null && cookies.size() > 0) {

for (Cookie item : cookies) {

cookieStore.add(url, item);

}

}

}

@Override

public List loadForRequest(HttpUrl url) {

List cookies = cookieStore.get(url);

return cookies;

}

}

構建RetrofitClient客戶端.

今天重要的環節來了,RetrofitClient主要負責創建具體Retrofit,和調度分發請求。設置格式工廠。添加cookie同步,構建OkHttpClient,添加BaseUrl,對加密證書https我沒做加入,希望讀者參考我的本系列文章自行加入,因為我不喜歡升伸手黨。

/**

* RetrofitClient

* Created by Tamic on 2016-06-15.

*/

public class RetrofitClient {

private static final int DEFAULT_TIMEOUT = 5;

private ApiService apiService;

private OkHttpClient okHttpClient;

public static String baseUrl = ApiService.Base_URL;

private static Context mContext;

private static RetrofitClient sNewInstance;

private static class SingletonHolder {

private static RetrofitClient INSTANCE = new RetrofitClient(

mContext);

}

public static RetrofitClient getInstance(Context context) {

if (context != null) {

Log.v("RetrofitClient", DevUtil.isDebug() + "");

mContext = context;

}

return SingletonHolder.INSTANCE;

}

public static RetrofitClient getInstance(Context context, String url) {

if (context != null) {

mContext = context;

}

sNewInstance = new RetrofitClient(context, url);

return sNewInstance;

}

private RetrofitClient(Context context) {

this(context, null);

}

private RetrofitClient(Context context, String url) {

if (TextUtils.isEmpty(url)) {

url = baseUrl;

}

okHttpClient = new OkHttpClient.Builder()

.addNetworkInterceptor(

new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.HEADERS))

.cookieJar(new NovateCookieManger(context))

.addInterceptor(new BaseInterceptor(mContext))

.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)

.build();

Retrofit retrofit = new Retrofit.Builder()

.client(okHttpClient)

.addConverterFactory(GsonConverterFactory.create())

.addCallAdapterFactory(RxJavaCallAdapterFactory.create())

.baseUrl(url)

.build();

apiService = retrofit.create(ApiService.class);

}

public void getData(Subscriber subscriber, String ip) {

apiService.getData(ip)

.subscribeOn(Schedulers.io())

.unsubscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(subscriber);

}

public void get(String url, Map headers, Map parameters, Subscriber subscriber) {

apiService.executeGet(url, headers, parameters)

.subscribeOn(Schedulers.io())

.unsubscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(subscriber);

}

public void post(String url, Map headers, Map parameters, Subscriber subscriber) {

apiService.executePost(url, headers, parameters)

.subscribeOn(Schedulers.io())

.unsubscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(subscriber);

}

}

細心的朋友已經發現上面代碼 在指定生產線程和消費線程的時候,步驟有點麻煩,每個api都得進行指定線程,那么可以利用rxJava的轉換器寫一個Transformer

Observable.Transformer schedulersTransformer() {

return new Observable.Transformer() {

@Override

public Object call(Object observable) {

return ((Observable)? observable).subscribeOn(Schedulers.io())

.unsubscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread());

}

};

}

那么api可以這樣優化了:

public Subscription getData(Subscriber subscriber, String ip) {

return apiService.getData(ip)

.compose(schedulersTransformer())

.subscribe(subscriber);

}

調用 RetrofitClient

RetrofitClient.getInstance(this).getData(new Subscriber() {

@Override

public void onCompleted() {

Toast.makeText(MainActivity.this, "加載完成", Toast.LENGTH_LONG).show();

}

@Override

public void onError(Throwable e) {

Toast.makeText(MainActivity.this, "失敗!: " + e.getMessage(), Toast.LENGTH_LONG).show();

}

@Override

public void onNext(ResponseBody ResponseBody) {

Toast.makeText(MainActivity.this, ResponseBody.toString(), Toast.LENGTH_LONG).show();

}

}, "21.22.11.33");

代碼很簡潔,在用到的地方獲取單列直接調用你需要的方法,在RxSubscriber回調中處理你的業務邏輯即可,無需考慮是否在主線程,其他調用方法同上。

很多時候BaseApiService無法滿足需求時,Retrofit增加了擴展接口create來創建你的API,接著調用execute就可以和RxJava關聯

//create? you APiService

MyApiService service =

RetrofitClient.getInstance(MainActivity.this).create(MyApiService.class);

// execute and add observable

RetrofitClient.getInstance(MainActivity.this).execute(

service.getData("21.22.11.33"), new Subscriber() {

@Override

public void onCompleted() {

}

@Override

public void onError(Throwable e) {

Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();

}

@Override

public void onNext(IpResult responseBody) {

Toast.makeText(MainActivity.this, responseBody.toString(),? Toast.LENGTH_LONG).show();

}

});}

取消

Subscription subscription =? RetrofitClient.getInstance(MainActivity.this)

.createBaseApi()

.getData(new BaseSubscriber(MainActivity.this) {

@Override

public void onError(ResponeThrowable e) {

Log.e("Lyk", e.code + " " + e.message);

Toast.makeText(MainActivity.this, e.message, Toast.LENGTH_LONG).show();

}

@Override

public void onNext(IpResult responseBody) {

Toast.makeText(MainActivity.this, responseBody.toString(), Toast.LENGTH_LONG).show();

}

}, "21.22.11.33");

subscription.unsubscribe();

Rxjava結合Retrofit,如何優雅的取消請求!

優雅的取消請看:http://www.lxweimin.com/p/d62962243c33

總結

本次封裝只對retrofit進行了簡單封裝,很多場景和需求還是存在缺陷,這種單列模式已不符合目前流行的Builder模式,本人已開始進行下一步的封裝工作,:

筆者已開發了新的框架開發Novate

https://github.com/NeglectedByBoss/Novate

源碼 GitHub :https://github.com/NeglectedByBoss/RetrofitClient

已全部更新完成

系列導讀

Retrofit 2.0(一) 超能實踐,完美支持Https傳輸

Retrofit2.0(二) 完美同步Cookie實現免登錄

Retrofit 2.0 超能實踐(三),輕松實現文件/圖片上傳

Retrofit 2.0 超能實踐(四),完成大文件斷點下載

基于Retrofit2.0 封裝的超好用的RetrofitClient工具類

玩轉IOC,教你徒手實現自定義的Retrofit框架

Rxjava和Retrofit 需要掌握的幾個實用技巧,緩存問題和統一對有無網絡處理問題

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 前言RxJava和Retrofit也火了一段時間了,不過最近一直在學習ReactNative和Node相關的姿勢,...
    AFinalStone閱讀 561評論 0 0
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,933評論 18 139
  • 我從去年開始使用 RxJava ,到現在一年多了。今年加入了 Flipboard 后,看到 Flipboard 的...
    Jason_andy閱讀 5,570評論 7 62
  • 總覺得心臟的位置不應該在左側,而在劍突,每次痛苦的時候,都是劍突在疼痛
    厭氧菌感染閱讀 210評論 0 0
  • 一、分答:付費問答模式 分答是由果殼網推出的知識類產品, 2016年5月因為王思聰等大V入駐平臺而迅速爆紅網絡。打...
    riddle汪汪閱讀 1,880評論 1 1