實Retrofit2.0結合RxAndroid現網絡請求網上有不少文章,這裏再也不詳細介紹服務器
Retrofit基本是一個業務請求,對應一個接口方法,由於其返回值不支持泛型,只能是具體的類。好處是結構清楚,缺點是業務請求就耦合的網絡接口,若是之後想分離網絡就很麻煩。並且開發人員還要同時定義每一個業務的請求接口,和具體的請求方式,對於大型APP,工做量很大,並且容易出錯。網絡
本文主要介紹如何對Retrofit2.0+RxAndroid封裝成網絡層,對業務使用隔離,使用者不須要知道網絡框架使用的是哪一種技術,只須要使用通用的接口,便可實現不一樣業務請求的調用。框架
下面這種泛型返回類型,Retrofit在運行是會報錯,啃爹啊。ide
@GET(ACTION_URL) <T extends BaseResult> Observable<T> requestNetwokData(@Query("a") String type, @QueryMap Map<String, String> options);
下面是變相的實現方式,基本技術不變,只是在服務器返回數據時作了一個簡單的處理。post
1. 返回的數據使用OKHttp原始的類型ResponseBodythis
2. 數據返回後,經過RxAndroid的map方法,強制根據調用者要求的類型進行轉換spa
@GET(ACTION_URL) Observable<ResponseBody> requestNetwokData(@Query("a") String type, @QueryMap Map<String, String> options);
public void startRequest(ServiceMap serviceMap, Map<String, String> paramMap) { NetworkResult networkResult = new NetworkResult(); networkResult.mServiceMap = serviceMap; Observable<ResponseBody> observable = mHttpApi.requestNetwokData(serviceMap.getmServiceType(), paramMap); subscribeOn(networkResult, observable); }
private void subscribeOn(final NetworkResult networkResult, final Observable<ResponseBody> observable) { Subscription subscription = observable.subscribeOn(Schedulers.io()) // subscribe()調用後並且在事件發送前執行 // 默認狀況下,doOnSubscribe()執行在subscribe()發生的線程 // 若是在doOnSubscribe()以後有subscribeOn()的話,它將執行在離它最近的subscribeOn()所指定的線程 .doOnSubscribe(new Action0() { @Override public void call() { postNetSubscribe(SubscribeNetwork.TAG_NET_ONSTART, networkResult); } }).subscribeOn(AndroidSchedulers.mainThread()) .map(new Func1<ResponseBody, BaseResult>() { @Override public BaseResult call(ResponseBody resBody) { NLog.e("retrofit", "map thread " + Thread.currentThread()); try { return JSON.parseObject(resBody.bytes(), networkResult.mServiceMap.getmClazz()); } catch (IOException e) { e.printStackTrace(); return null; } } }) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<BaseResult>() { @Override public void onCompleted() { postNetSubscribe(SubscribeNetwork.TAG_NET_ONCOMPLETED, networkResult); } @Override public void onError(Throwable e) { postNetSubscribe(SubscribeNetwork.TAG_NET_ONERROR, networkResult); } @Override public void onNext(BaseResult baseResult) { NLog.e("retrofit", "onNext thread " + Thread.currentThread()); networkResult.mResponseResult = baseResult; postNetSubscribe(SubscribeNetwork.TAG_NET_ONRESULT, networkResult); } }); // add方法內作了線程同步功能 mCompositeSubscription.add(subscription); }
上面就是本人的變相處理方式,哪位大神有好的方法,歡迎指導。.net
RxBus post方法遇到的坑線程
1. 使用post方法通知訂閱者,網絡數據返回code
/** * 給訂閱者髮網絡處理消息 * @param tag * @param networkResult */ private void postNetSubscribe(String tag, @NonNull NetworkResult networkResult) { if (networkResult.mResponseResult == null) { // 保證mResponseResult永遠都不爲null networkResult.mResponseResult = new BaseResult(); } RxBus.get().post(tag, networkResult); }
2. 通用的訂閱者,接收網絡數據返回,再分發給不一樣界面
public class SubscribeNetwork { private INetworkListener networkListener; public SubscribeNetwork(INetworkListener listener) { this.networkListener = listener; } public void register() { // 網絡請求處理結果監聽 RxBus.get().register(this); } public void unregister() { // 解除網絡處理結果監聽 RxBus.get().unregister(this); } @Subscribe(tags = {@Tag(TAG_NET_ONRESULT)}) public void subscribeNetResult(NetworkResult networkResult) { if (networkListener != null) { networkListener.onNetResult(networkResult); } } }
3. SubscribeNetwork的註冊,是在Fragment建立時,初始化的。
問題:
在使用ViewPager + Fragment時,默認會建立2個Fragment,即會註冊2個RxBus的訂閱者。
不論第二個Fragment是否進行網絡請求,再第一個網絡請求返回時,都會調用subscribeNetResult方法,進而調用networkListener的回調。
因此致使Fragment的網絡回調會屢次調用。
解決:
只能使用接口方式,進行返回,不使用rxbus的post方式。
/** * 給訂閱者髮網絡處理消息 * @param tag * @param networkResult */ private void postNetSubscribe(String tag, @NonNull NetworkResult networkResult) { if (networkResult.mResponseResult == null) { // 保證mResponseResult永遠都不爲null networkResult.mResponseResult = new BaseResult(); } // RxBus.get().post(tag, networkResult); if (mNetworkListener != null) { if (INetworkListener.TAG_NET_ONSTART.equals(tag)) { mNetworkListener.onNetStart(networkResult); } else if (INetworkListener.TAG_NET_ONRESULT.equals(tag)) { mNetworkListener.onNetResult(networkResult); } else if (INetworkListener.TAG_NET_ONCOMPLETED.equals(tag)) { mNetworkListener.onNetCompleted(networkResult); } else if (INetworkListener.TAG_NET_ONERROR.equals(tag)) { mNetworkListener.onNetError(networkResult); } } }