RxJava2开发小记:先加载缓存再请求网络之简单实现

关于缓存

用户角度:
做客户端,大部分时候都在追求良好的用户体验,缓存,就要达到一个缓兵之计的效果。因为用户永远是“暴躁”的,页面加载要是有缓存先展示出来,用户就会安心很多。这是一种视觉上的舒服,大多数用户并不在乎这个数据从哪来。
开发者角度:
对于客户端程序来说,网络状况是未知而不稳定的,在耗时上面,一次网络请求可能大于本地数据读取好几个数量级。并且,某些及时性不高的数据,并不需要每次都从服务端请求,而是按过期时间来判断是否需要更新缓存,这样也能尽可能地减轻服务器压力。

总结一下上面的开篇废话就是,用户是暴躁的,服务器是脆弱的,唯一坚挺并且逆来顺受的就是客户端了哈哈哈!

正文

目标
望闻问切四部曲:
UI层发起数据获取意愿(望),打听是否能加载缓存(闻),再访问网络进行远程请求(问),最后刷新缓存至本地存储并返回数据给UI层(切)。
药材
读缓存的Observable一个(localDataObservable)
请求网络数据的Observable一个(remoteDataObservable)
关键性的串联操作符contact一个
上药

// 闻:本地缓存
Observable<DataClass> localDataObservable = Observable.create((ObservableOnSubscribe<DataClass>)
        emitter -> {
            DataClass cacheData = null;
            try {
                cacheData = ... // 缓存数据来源根据具体的业务决定
            } catch (Exception e) {
                // 当场抓获,防止异常导致整个事件流中断,致使网络请求无法进行
            }
            if (cacheData != null) {
                // 没毛病就传递给UI层,onNext可以多次调用,比如在循环体中使用很方便
                emitter.onNext(cacheData);
            }
            emitter.onComplete(); // 本次事件结束了,把执行权交给下一个可能存在的事件
        })
        .subscribeOn(Schedulers.io()); // 读缓存当然要在子线程
// 问:网络数据
Observable<DataClass> remoteDataObservable = RetrofitFactory.createRequest()
        .getRemoteData()
        .subscribeOn(Schedulers.io())
        .map(dataResponse -> {
            DataClass remoteData = dataResponse;
            // 读了新数据就该写缓存了
            // ...具体可以做一些类似expireTime的判断,还可以在此处再订阅一个异步写缓存的Observable,达到读写分离的效果
            return remoteData;
        });

由于这里是用到了RxJava2+Retrofit2的结构,上述的RetrofitFactory.createRequest().getRemoteData()是对Retrofit进行了简单封装,具体请见:RxJava2开发小记:用CompositeDisposable来“安排”Retrofit网络请求

// 使用contact操作符将两个事件串联起来,当上述的onComplete执行过后,就会开始进行网络请求
Observable.concat(localDataObservable, remoteDataObservable)
        .observeOn(AndroidSchedulers.mainThread(), true) // 这里delayError设为true,防止onNext在下游还没消费完,就被onComplete结束掉了
        .subscribe(data -> {
            // 最终得到的data对于调用侧的UI层来说,并不需要关心其来源,只管消费就好了
            // ... 展示到UI
        }, throwable -> {
           // 网络请求的异常捕捉,因为读缓存过程中的异常已经被我们提前捕捉了,这里就不会再出现
        });

OK,药到病除,这里基本上是一个模板,以及一些细节处理。
运用到实际业务中还需要大家细细优化。比如说,一些页面可能并不需要每次都串联网络请求,而是需要先判断缓存是否过期,那么就可以在localDataObservable中主动抛出onError来中断事件流,以达到阻止网络请求的目的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值