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

weixin_34249678發表於2017-11-04

      簡書 :天天大保建

      原文地址:

      http://www.jianshu.com/p/29c2a9ac5abf


2022038-71bdab0afae24005.png

基於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.jianshu.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 需要掌握的幾個實用技巧,快取問題和統一對有無網路處理問題

相關文章