RxJava2 + Retrofit2 優(yōu)雅簡(jiǎn)潔封裝

RxJava2 封裝主要變化

  • Transformer的變化:RxJava1.X為rx.Observable.Transformer接口, 繼承自Func1<Observable<T>, Observable<R>>, RxJava2.X為io.reactivex.ObservableTransformer<Upstream, Downstream>,是一個(gè)獨(dú)立的接口。
  • Flowable則是FlowableTransformer,如果你使用Flowable,以下ObservableTransformer替換FlowableTransformer即可。

gitHub 項(xiàng)目地址

RxJava2 + Retrofit2.jpg

封裝方案

1、封裝 Rx 線程相關(guān)

RxSchedulersHelper:

/**
 * Created by weiss on 17/1/16.
 */
public class RxSchedulers {
    public static <T> ObservableTransformer<T, T> io_main() {
        return upstream ->
                upstream.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }
}

封裝后:

Api.getInstance().movieService
                .getGankData("Android",1)
                .compose(RxSchedulers.io_main());

2、封裝 處理服務(wù)器返回?cái)?shù)據(jù),管理 RxJava生命周期

HttpResult:

/**
 * Created by Weiss on 2017/1/11.
 */

public class HttpResult<T> implements Serializable {
    public String code;
    public String msg;
    public boolean hasmore;
    public T data;

    public static String SUCCESS = "000";
    public static String SIGN_OUT = "101";//token驗(yàn)證失敗
    public static String SHOWTOAST = "102";//顯示Toast

    public boolean isSuccess() {
        return SUCCESS.equals(code);
    }

    public boolean isTokenInvalid() {
        return SIGN_OUT.equals(code);
    }

    public boolean isShowToast() {
        return SHOWTOAST.equals(code);
    }

    public boolean hasMore() {
        return hasmore;
    }
}

BaseRxActivity:


/**
 * 管理RxJava生命周期,避免內(nèi)存泄漏
 * RxJava處理服務(wù)器返回
 *
 * Created by Weiss on 2016/12/23.
 */

public abstract class BaseRxActivity extends BaseActivity {

    private CompositeDisposable disposables2Stop;// 管理Stop取消訂閱者者
    private CompositeDisposable disposables2Destroy;// 管理Destroy取消訂閱者者

    protected abstract int getLayoutId();

    protected abstract void initView();

    /**
     * Rx優(yōu)雅處理服務(wù)器返回
     *
     * @param <T>
     * @return
     */
    public <T> ObservableTransformer<HttpResult<T>, T> handleResult() {
        return upstream ->{
                return upstream.flatMap(result -> {
                            if (result.isSuccess()) {
                                return createData(result.data);
                            } else if (result.isTokenInvalid()) {
                                //處理token失效,tokenInvalid方法在BaseActivity 實(shí)現(xiàn)
                                 tokenInvalid();
                            } else {
                                return Observable.error(new Exception(result.msg));
                            }
                            return Observable.empty();
                        }

                );
        };
    }

    private <T> Observable<T> createData(final T t) {
        return Observable.create(subscriber -> {
            try {
                subscriber.onNext(t);
                subscriber.onComplete();
            } catch (Exception e) {
                subscriber.onError(e);
            }
        });
    }

    public boolean addRxStop(Disposable disposable) {
        if (disposables2Stop == null) {
            throw new IllegalStateException(
                    "addUtilStop should be called between onStart and onStop");
        }
        disposables2Stop.add(disposable);
        return true;
    }

    public boolean addRxDestroy(Disposable disposable) {
        if (disposables2Destroy == null) {
            throw new IllegalStateException(
                    "addUtilDestroy should be called between onCreate and onDestroy");
        }
        disposables2Destroy.add(disposable);
        return true;
    }

    public void remove(Disposable disposable) {
        if (disposables2Stop == null && disposables2Destroy == null) {
            throw new IllegalStateException("remove should not be called after onDestroy");
        }
        if (disposables2Stop != null) {
            disposables2Stop.remove(disposable);
        }
        if (disposables2Destroy != null) {
            disposables2Destroy.remove(disposable);
        }
    }

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (disposables2Destroy != null) {
            throw new IllegalStateException("onCreate called multiple times");
        }
        disposables2Destroy = new CompositeDisposable();
    }

    public void onStart() {
        super.onStart();
        if (disposables2Stop != null) {
            throw new IllegalStateException("onStart called multiple times");
        }
        disposables2Stop = new CompositeDisposable();
    }

    public void onStop() {
        super.onStop();
        if (disposables2Stop == null) {
            throw new IllegalStateException("onStop called multiple times or onStart not called");
        }
        disposables2Stop.dispose();
        disposables2Stop = null;
    }

    public void onDestroy() {
        super.onDestroy();
        if (disposables2Destroy == null) {
            throw new IllegalStateException(
                    "onDestroy called multiple times or onCreate not called");
        }
        disposables2Destroy.dispose();
        disposables2Destroy = null;
    }
}

封裝后 (BaseRxActivity的子類使用):

addRxDestroy(Api.getInstance().movieService
                .getGankData("Android",1)
                .compose(RxSchedulers.io_main())
                .compose(handleResult())
                .省略
);

handleResult為什么不新建一個(gè)類處理呢?因?yàn)楹芏喈惓L幚硇枰猚ontext對(duì)象,或者和BaseActivity有千絲萬(wàn)縷的聯(lián)系,BaseRxActivity繼承BaseActivity可以很簡(jiǎn)潔優(yōu)雅處理各種異常。比如token失效,是需要跳轉(zhuǎn)到登錄頁(yè)面的。在新建一個(gè)類中,不能持有context對(duì)象,只能使用Application的Context,同時(shí)方便與Activity通信交互滿足各種需求。BaseRxActivity還可以管理RxJava生命周期。

3、異常處理


/**
 * Created by Weiss on 2017/2/9.
 */

public class RxException<T extends Throwable> implements Consumer<T> {

    private static final String TAG = "RxException";

    private static final String SOCKETTIMEOUTEXCEPTION = "網(wǎng)絡(luò)連接超時(shí),請(qǐng)檢查您的網(wǎng)絡(luò)狀態(tài),稍后重試";
    private static final String CONNECTEXCEPTION = "網(wǎng)絡(luò)連接異常,請(qǐng)檢查您的網(wǎng)絡(luò)狀態(tài)";
    private static final String UNKNOWNHOSTEXCEPTION = "網(wǎng)絡(luò)異常,請(qǐng)檢查您的網(wǎng)絡(luò)狀態(tài)";

    private Consumer<? super Throwable> onError;
    public RxException(Consumer<? super Throwable> onError) {
        this.onError=onError;
    }

    /**
     * Consume the given value.
     *
     * @param t the value
     * @throws Exception on error
     */
    @Override
    public void accept(T t) throws Exception {
        if (t instanceof SocketTimeoutException) {
            Log.e(TAG, "onError: SocketTimeoutException----" + SOCKETTIMEOUTEXCEPTION);
            ToastUtils.show(SOCKETTIMEOUTEXCEPTION);
            onError.accept(new Throwable(SOCKETTIMEOUTEXCEPTION));
        } else if (t instanceof ConnectException) {
            Log.e(TAG, "onError: ConnectException-----" + CONNECTEXCEPTION);
            ToastUtils.show(CONNECTEXCEPTION);
            onError.accept(new Throwable(CONNECTEXCEPTION));
        } else if (t instanceof UnknownHostException) {
            Log.e(TAG, "onError: UnknownHostException-----" + UNKNOWNHOSTEXCEPTION);
            ToastUtils.show(UNKNOWNHOSTEXCEPTION);
            onError.accept(new Throwable(UNKNOWNHOSTEXCEPTION));
        } else {
            Log.e(TAG, "onError:----" + t.getMessage());
            onError.accept(t);
        }
    }
}

封裝后 (BaseRxActivity的子類使用):

addRxDestroy(Api.getInstance().movieService
                .getGankData("Android",1)
                .compose(RxSchedulers.io_main())
                .compose(handleResult())
                .subscribe(httpResult -> adapter.setItems(data),
                                new RxException<>(e ->e.printStackTrace()))
);

4、多頁(yè)請(qǐng)求封裝

實(shí)體類:

/**
 * Created by Weiss on 2017/1/20.
 */

public class Gank extends BaseListEntity {
    @Override
    public Observable<HttpResult<List<Gank>>> getPage(int page) {
        return GankApi.getInstance().service.getGankData(param.get("gank"), page)
                .compose(RxSchedulers.io_main());
    }

}

實(shí)體類繼承 BaseListEntity,實(shí)現(xiàn)getPage方法即可。

UI視圖:

public class MainActivityFragment extends BaseRxFragment {
    @BindView(R.id.ptrRecyclerView)
    PtrRecyclerView ptrRecyclerView;

    private MultiTypeAdapter adapter;

    public MainActivityFragment() {
    }


    @Override
    protected int getLayoutId() {
        return R.layout.fragment_main;
    }

    @Override
    protected void initView() {
        ptrRecyclerView.setParam("gank","Android");
        adapter = new MultiTypeAdapter();
        adapter.register(Gank.class,new GankViewProvider());
        ptrRecyclerView.setAdapter(adapter,new Gank());
    }
}

只需要寫一個(gè)適配器和實(shí)體類,輕松實(shí)現(xiàn)多頁(yè)請(qǐng)求,PtrRecyclerView下拉刷新和上拉加載是會(huì)自動(dòng)調(diào)用getPage()方法獲取數(shù)據(jù)。
PtrRecyclerView目前只是簡(jiǎn)單實(shí)現(xiàn)下拉刷新和上拉加載,有空會(huì)完善,當(dāng)然例子也會(huì)完善。當(dāng)然PtrRecyclerView的封裝會(huì)根據(jù)RecyclerView原生的方法名參數(shù),減少學(xué)習(xí)成本。

后記

還可以封裝網(wǎng)絡(luò)加載對(duì)話框,這個(gè)看個(gè)人喜好,同樣以上封裝同樣可以看個(gè)人喜好和項(xiàng)目需求自由組裝。
RxJava2 + Retrofit2 封裝 giithub 源碼地址

相關(guān)鏈接

RxJava 2.0有什么不同(譯)
探索專為 Android 而設(shè)計(jì)的 RxJava 2
RxJava2 + Retrofit2 開發(fā)框架

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容