最近加入了新的工作,Android産品用了RX+retrofit作為網絡互動架構,以前完全沒用過,隻有自己補一補。這裡與大家分享一下學習成果,也便于自己日後複習。類似的文章特别多,封裝也大同小異,特别記錄一篇是希望自己将看過的東西能夠真正了解變成自己的東西。
private void requestLogin(String name,String pwd){
APILoader personAPILoader=new APILoader();
personAPILoader.login(name,pwd)
.doOnNext(new Consumer<LoginBean>() {
@Override
public void accept(LoginBean loginBean) throws Exception {
}
})
.subscribe(new NetDisposable<>());
}
複制
上面是筆者發起登陸請求的完整代碼,還是比較簡潔了吧。我們在doOnNext()中處理我們的結果邏輯,它會執行在onNext()之前。
下面我們由外至内一步一步來解析整套流程。
APILoader以及ObjectLoader
public class APILoader extends ObjectLoader {
private PersonAPI mPersonAPI;
public APILoader(){
mPersonAPI=RetrofitServiceManager.getInstance().create(PersonAPI.class);
}
public Observable<LoginBean> login(String name,String pwd){
return observe(mPersonAPI.loginRX(name,pwd));
}
}
public class ObjectLoader {
protected <T> Observable<T> observe(Observable<T> observable){
return observable
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
}
複制
ObjectLoader是我們自己實作的Loader父類,用于所有Loader類繼承,封裝了observe方法,參數和傳回值都是Observable,作用是統一對Observable加工,處理一些重複操作,例如觀察者與被觀察者的線程處理。
APILoader繼承自ObjectLoader,用于管理retrofit的ServiceAPI接口,避免每次使用都需要去create一次。所有的Loader統一繼承ObjectLoader,對observable進行統一配置。
看到這裡我們又出現了兩個新玩意,分别是單例類RetrofitServiceManager以及接口PersonAPI。
接口PersonAPI
public interface PersonAPI {
@GET("td_web/td/login/")
Call<LoginBean> login(@Query("name") String name,@Query("pwd") String pwd);
@GET("td_web/td/login/")
Observable<LoginBean> loginRX(@Query("name") String name, @Query("pwd") String pwd);
}
複制
這裡的PersonAPI就是我們說的retrofit的ServiceAPI,在我看來是retrofit的精髓,采用接口注入的方式,建立和管理我們的請求接口
RetrofitServiceManager
public class RetrofitServiceManager {
private static final int DEFAULT_TIME_OUT = 5;//逾時時間 5s
private static final int DEFAULT_READ_TIME_OUT = 10;//讀寫逾時
private static final String BASE_URL="http://222.211.90.120:6071/";//根位址
private static RetrofitServiceManager retrofitServiceManager;
//日志顯示級别
private Retrofit mRetrofit;
/**
* 擷取RetrofitServiceManager
* @return
*/
public synchronized static RetrofitServiceManager getInstance(){
if(retrofitServiceManager==null) return new RetrofitServiceManager();
return retrofitServiceManager;
}
private RetrofitServiceManager(){
// 建立 OKHttpClient
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS);//連接配接逾時時間
builder.writeTimeout(DEFAULT_READ_TIME_OUT,TimeUnit.SECONDS);//寫操作 逾時時間
builder.readTimeout(DEFAULT_READ_TIME_OUT,TimeUnit.SECONDS);//讀操作逾時時間
builder.retryOnConnectionFailure(true);
// 添加公共參數攔截器
BasicParamsInterceptor basicParamsInterceptor = new BasicParamsInterceptor.Builder()
.addHeaderParam("paltform","android")
.addHeaderParam("userToken","1234343434dfdfd3434")
.addHeaderParam("userId","123445")
.build();
//添加日志列印攔截器
HttpLoggingInterceptor loggingInterceptor=new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);//設定日志顯示級别
builder.addInterceptor(basicParamsInterceptor);
builder.addInterceptor(loggingInterceptor);
// 建立Retrofit
mRetrofit = new Retrofit.Builder()
.client(builder.build())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build();
}
/**
* 擷取對應的Service
* @param service Service 的 class
* @param <T>
* @return
*/
public <T> T create(Class<T> service){
return mRetrofit.create(service);
}
}
複制
retrofitServiceManager管理的是ServiceAPI的建立,對外公布create方法,傳回ServiceApi執行個體
同時對OkHttpClient進行了封裝和引入,可以對請求的公共參數,請求時間等進行添加和限制。
我們可以看到,這個一個單例類,在構造方法中我們可以統一的OkHttpClient進行配置以及添加攔截器等等。同時統一建構Retrofit的屬性,隻需要對外提供create方法,建構不同的ServiceAPI執行個體就可以了。
這裡值得多提一句的是
HttpLoggingInterceptor
。他是retrofit的日志攔截器,用于列印請求位址等等資訊,可以通過setLevel設定列印資訊的級别(級别越高,内容約詳細)。retrofit做網絡請求想要列印請求資訊,暫時隻發現這個方法,不像OkHttp3可以直接拿到url。
NetObserver網絡請求觀察者
一個簡單封裝的網絡請求統一觀察者,對網路請求常見的錯誤進行了管理和列印。
public class NetObserver<T> extends DisposableObserver<T> {
private String message="";
private final String TAG="NetObserver";
@Override
public void onNext(T t) {
}
@Override
public void onError(Throwable e) {
if (e instanceof HttpException) {
message = "網絡錯誤";
} else if (e instanceof SocketTimeoutException) {
message = "網絡連接配接逾時";
} else if (e instanceof ConnectException) {
message = "連接配接失敗";
} else if (e instanceof IOException) {
message = "網絡錯誤";
} else if (e instanceof javax.net.ssl.SSLHandshakeException) {
message = "證書驗證失敗";
} else if (e instanceof JsonParseException
|| e instanceof JSONException
|| e instanceof ParseException) {
//均視為解析錯誤
message="資料解析出現錯誤";
} else {
message = "未知錯誤";
}
Log.e(TAG,message);
}
@Override
public void onComplete() {
}
}
複制
參考文章:
【Android】RxJava2+Retrofit2+OkHttp3的基礎、封裝和項目中的使用
本文源碼:
Retrofit+RX學習Github源碼位址