zoukankan      html  css  js  c++  java
  • RxJava + Retrofit 的实际应用场景

        关于

    RxJava Retrofit

        很多篇文章都有详细的说明,在这里我想分享一个具体的使用案例,在我的开源项目 

    就看天气

         里的实际应用。也希望跟大家探讨如何优雅的使用。

    准备

    项目中用到的依赖:

    compile 'io.reactivex:rxjava:1.1.0'
    compile 'io.reactivex:rxandroid:1.1.0'
    compile 'com.google.code.gson:gson:2.4'
    compile 'com.squareup.retrofit2:retrofit:2.0.2'
    compile 'com.squareup.retrofit2:converter-gson:2.0.2'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
    compile 'com.squareup.okhttp3:okhttp:3.0.1'
    compile 'com.squareup.okhttp3:logging-interceptor:3.0.1'
    compile 'com.squareup.okio:okio:1.6.0'

    因为要用到网络,所以千万别忘记了这个权限。

    <uses-permission android:name="android.permission.INTERNET"/>

    组件

    Rx 封装的工具

    使用compose操作符

    compose()里接收一个Transformer对象,Transformer继承自Func1<Observable<T>, Observable<R>>,可以通过它将一种类型的Observable转换成另一种类型的Observable

    RxSchedulerHelper

    封装 Rx 线程相关操作

    public static <T> Observable.Transformer<T, T> rxSchedulerHelper() {
    return tObservable -> tObservable.subscribeOn(Schedulers.io())
    .unsubscribeOn(AndroidSchedulers.mainThread())
    .observeOn(AndroidSchedulers.mainThread());
    }

    handleResult

    封装 API 请求后统一处理

    public static <T> Observable.Transformer<Result<T>, T> handleResult() {
    return resultObservable -> resultObservable.flatMap(tResult -> {
    if (tResult.code == 1) {
    return createData(tResult.data);
    } else {
    return Observable.error(new ApiException(tResult.code));
    }
    });
    }

    RetrofitSingleton

    自己封装了下 Retrofit。可以学习下小艾的方式

    自己将请求是写在该类,使用者只需要关心如何处理拿到的数据和相应的 UI 操作。

    public Observable<Weather> fetchWeather(String city) {
    return apiService.mWeatherAPI(city, C.KEY)
    .filter(weatherAPI -> weatherAPI.mHeWeatherDataService30s.get(0).status.equals("ok"))
    .map(weatherAPI -> weatherAPI.mHeWeatherDataService30s.get(0))
    .compose(RxUtils.rxSchedulerHelper());
    }
    public Observable<VersionAPI> fetchVersion() {
    return apiService.mVersionAPI(C.API_TOKEN).compose(RxUtils.rxSchedulerHelper());
    }

    使用

    网络拉取读取缓存用 Rx 结合。
    这里就要使用 concat 操作符,官方解释.

    首先看看获取网络是如何写的:

    private Observable<Weather> fetchDataByNetWork() {
    String cityName = Util.replaceCity(mSetting.getCityName());
    return RetrofitSingleton.getInstance()
    .fetchWeather(cityName)
    .onErrorReturn(throwable -> {
    PLog.e(throwable.getMessage());
    return null;
    });
    }

    这里的 onErrorReturn 待会儿说。

    再来看看读取缓存的代码:

    private Observable<Weather> fetchDataByCache() {
    return Observable.defer(() -> {
    Weather weather = (Weather) aCache.getAsObject(C.WEATHER_CACHE);
    return Observable.just(weather);
    });
    }

    然后我们将他们连接起来:

    private void load() {
    Observable.concat(fetchDataByNetWork(), fetchDataByCache())
    .first(weather -> weather != null)
    .doOnError(throwable -> {
    mErroImageView.setVisibility(View.VISIBLE);
    mRecyclerView.setVisibility(View.GONE);
    })
    .doOnNext(weather -> {
    mErroImageView.setVisibility(View.GONE);
    mRecyclerView.setVisibility(View.VISIBLE);
    })
    .doOnTerminate(() -> {
    mRefreshLayout.setRefreshing(false);
    mProgressBar.setVisibility(View.GONE);
    })
    .subscribe(observer);
    }

    concat + first 连接和过滤的操作实现了,网络+缓存的逻辑。

    刚刚为什么说要在网络代码那里使用 onErrorReturn 呢?

    如果不写,网络发生异常的话,整个流就会直接走 onError ,不会执行到读取缓存的流。

    结语

    Rx 的各种操作符的不同组合就可以实现不同的效果。本身 Rx 封装已经足够好了,我们加工的时候一定要想到是否破坏了他本身的优雅。

    因为 Rx 是一种数据流链式结构的编程思想,我们在封装时应该不能打断其链式结构。

  • 相关阅读:
    结构体排序中sort的自定义函数cmp()
    c++中清空输入缓冲区的方法(做cf的时候炸了)
    求第k小的数
    数论—约数
    HDU递归求解专题练习
    62、rdp报表
    61、inputTree
    60、list集合的各种姿势的排序
    59、table移动高亮
    13、docker安装nginx
  • 原文地址:https://www.cnblogs.com/android-blogs/p/5984048.html
Copyright © 2011-2022 走看看