1. 程式人生 > >Android okhttp + rxJava + retorfit2使用心得

Android okhttp + rxJava + retorfit2使用心得

okhttp出來已經很久了,rxjava也是近兩年火起來的框架,框架的使用能讓我們寫出更為優秀的程式碼,這裡主要介紹square公司提供的框架,記錄一下對Android新的http請求極具擴充套件性的寫法。這裡主要用到的是觀察者模式,先說下概念,Observable是被觀察者,Observer是觀察者,
兩者之間通過subcriber訂閱者,由Observablesubcribe通知Observer實現互動。

對於一個普通的http get請求,這裡主要進行http通訊的肯定是okhttp,這點毫無疑問,因此肯定需要一個okhttp物件,於是有了下面的程式碼
`OkHttpClient httpClient = new OkHttpClient.Builder()
.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.cookieJar(new CookieManager(context)).build()

這裡主要設定超時時間和Cookie的管理,這裡的CookieManager是參考httpClient的CookieManager自己重寫的一個類,先不去糾結。
接下來需要retorfit和rxjava框架來解決http請求和處理資料時需要的一堆程式碼,及子執行緒無法更新UI等問題,呼叫非常簡單。先匯入包,

compile 'io.reactivex:rxjava:1.1.0'
compile 'io.reactivex:rxandroid:1.1.0'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'

建立一個retorfit物件:
Retrofit retrofit_user = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl(BASE_URL)
.client(httpClient)
.build();

addConverterFactory新增Gson解析方式,這裡也可以自定義解析格式,還有xml解析的Convert,String的Convert。
addCallAdapterFactory新增支援返回Observable物件,如果你在返回時用的Call,可以不去新增。
接下來核心請求方法來了,定義一個UserInterface介面,比如我們要獲取使用者資訊,程式碼如下:@GET("/api/user/details")
Observable<UserDetailsInfo> getUserInfo(@Query("userId") String userId);

@GET是retrofit2.http.GET包下面的註解,引數是URL,拼接前面定義retorfit物件的baseUrl,@Query是拼接userId到這個連結後面,如baseurl為http//:10.1.22.53:8080,userid=2222,則這句url等價於http//:10.1.22.53:8080/api/user/details?userId=2222,同理@POST方法也是一樣。這裡返回的物件是Observable,用過java Gson的人應該知道,這種方式解析的好處在於,只要返回的json名字對應上了,不需要像Android中的JSON類去寫parse方法。如伺服器返回{“errCode”: 403,
“message”: “aaa”},則這裡定義的UserDetailsInfo為:

   class UserDetailsInfo{
       private int errCode;
       private Stirng message;
   } 

這樣就得到了伺服器返回的UserDetailsInfo物件。
接下來要去建立這個介面給retorfit,
mUserInterface = retrofit_user.create(UserInterface.class);
這裡原始碼是通過位元組碼去建立的方法,接下來去呼叫UserInterface定義的getUserInfo方法,並且訂閱。
需要一個訂閱者,

Subscriber<UserDetailsInfo> userSubscriber = new Subscriber<UserDetailsInfo>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(UserDetailsInfo userDetailsInfo) {
}
};

這裡是rxjava提供的api,讓我們不用再通過handler去解決子執行緒UI更新問題,在這三個回撥方法中,可以直接去更新UI,設計錯誤介面。
一切就緒,最後開始訂閱:

` mUserInterface.getUserInfo(userid)
            .onErrorReturn(new Func1<Throwable,UserDetailsInfo>() {
                @Override
                public UserDetailsInfo call(Throwable throwable) {
                    return null;
                }
            })
            .subscribeOn(Schedulers.io())
            .unsubscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(subscriber);`

這裡基本是通用寫法, subscribeOn引數Schedulers.io()指的是訂閱通過網路IO的形式,observeOn的AndroidSchedulers.mainThread()是在主執行緒返回執行,subscribe是最終的訂閱方法。
以上是正常情況下我們需要做的。
下面說下我在使用過程中遇到的坑:
1.對於POST請求,例如登入,後臺處理登入時必須將使用者名稱密碼以json的形式,放在post請求的body中,這裡需要將定義的map,轉化為json資料,在介面中傳到@body欄位中。
2.對於json的返回資料,如果是jsonArray的,需要用list這種方式定義欄位。
3.不知道伺服器返回什麼樣的資料,要看到伺服器的String資訊,返回值用Response,Response是retrofit2.Response,ResponseBody是okhttp3.ResponseBody,如要修改返回欄位,需要修改Subscribe物件的引數,getUserInfo介面的返回值。
遺留問題:
對於服務端返回的資料解析這塊,如果返回的不是json物件或者你定義的資料結構和服務端返回的欄位有錯誤,排錯就需要改為responseBody,這裡的改動牽一髮而動全身,感覺不是很好用,要檢視時要修改多處地方,希望能有更好的解決方案討論下。