1、zip
功能说明:合并从不同的数据源获取的数据(有两个接口),然后展示数据.
我在项目中的应用是:将第三方广告接口返回的数据 夹杂 到自加平台返回的广告数据 并且展示出来。
详情使用请参见:zip在项目中的使用
2、flatMap
作用:网络嵌套请求。
我在项目中的应用:服务器出于安全考虑,一些接口需要传入token才能返回正确的数据。而token需要从另一个接口获得。这时使用flatMap发起嵌套的网络请求就非常合适,这样的代码会非常的清晰、整洁。
示例:
1)接口
2)获取到的请求实体:TokenEntity和MyInfoEntity(我就不给大家列了)
3)使用 flatMap 发起嵌套的网络请求:
运行结果:
这样就搞定了是不是很简单。不知道大家听懂登录没有。我再举个例子:当用户注册成功以后,再去做登录,这个也是可以用flatMap来实现的。
3、retrywhen
我在项目中的具体使用:我们都知道Token并非是一次性的,而是可以多次使用的。(而我的项目中Token发生改变的情形是账号在另一台手机上登录,这时token就发生了改变,而当前的这架手机再发起数据请求时是请求不到数据的,因为这时的token发生改变)。由于token失效而获取数据失败,这种情景是非常的常见,这样的token处理起来也是比较麻烦的。因为多处的接口都需要token,我们需要把它保存起来,并且当发现token失效的时候要能够自动重新获取新的token来访问因为token失效的接口。如果这样使用原来的Callback来实现是非常的困难。而如果使用 了太容易When来实现的话那就非常非常的简单了。
在项目中的使用示例:
//假设从共享参数获取到的Token
String token="1234";
//可重试的最大次数
int maxCount=3;
//当前重试的次数
int retryCount=0;
private void doRxJava6() {
RetrofitFactory.getRetrofit().create(NetApi.class).requestMyInfo(token)
.subscribeOn(Schedulers.io())
.retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(@NonNull Observable<Throwable> throwableObservable) throws Exception {
//捕获异常
return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(@NonNull Throwable throwable) throws Exception {
//判断是否是空指针异常,如果是空指针异常,那表示Token已经过期(我的后台如果Token发生错误返回的就是空指针异常)
if (throwable instanceof NullPointerException){
//表示Token已经过期,需要获取新的Token
//判断重试的次数
if (retryCount<maxCount){
//记录重试的次数
retryCount++;
Log.e("RxJava","重试的次数:"+retryCount);
RetrofitFactory.getRetrofit().create(NetApi.class).requestToken("17310851776","123456")
.subscribeOn(Schedulers.io())
.doOnNext(new Consumer<TokenEntity>() {
@Override
public void accept(@NonNull TokenEntity tokenEntity) throws Exception {
//保存一下新的Token
token=tokenEntity.getData().getToken();
}
});
//让原始的Observable重新发送数据
return Observable.just(1);
}else{
//表示超过了重试次数,让原始的Observable不在发送数据
return Observable.error(throwable);
}
}
return Observable.error(throwable);
}
});
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Object>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull Object o) {
System.out.println("接收到数据:"+o);
}
@Override
public void onError(@NonNull Throwable e) {
System.out.println("对Error作出响应:"+e);
}
@Override
public void onComplete() {
}
});
}
这个理解起来有点复杂,建议大家动手写一写就明白了其中的道理了。
4、从磁盘 或者 内存 获取缓存数据
流程图:
数据缓存在App中我很会很经常的和缓存打交道。
1、数据的时效性:
常见的此类应用:新闻、社区。这类的app无论是否存在缓存,都是请求网络。这类的app的特点在于先显示缓存的数据,然后再去请求网络,显示最新的数据。
2、数据定期更新或者更新不频繁:
此类常见的app:小说,应用市场等。这类应用特点是:给缓存设置一个过期的事件,只要时间未过期就优先使用缓存的数据。当缓存过期以后再访问网络获取新的数据。
3、不需要缓存:打车、金融服务等。此类App的需要的是实时性,所有缓存就没有意义了。
而缓存中我们离不开的就是图片的缓存。因为图片缓存比较特殊,它占用的内存较大,即使是本地的图片,也会有较大的延迟。所以用该用到的是三级缓存策略:内存+本地+网络。但是这其中也会有很多的问题存在:
1、内存不足(OOM)
如果把图片全部缓存到内存,我相信过不了多久就会出现OOM。所以,只能部分的缓存到内存。这时候,内存缓存的问题就变成了选择缓存图片的问题。常见的选择策略是LRU(近期最少使用的算法)。
2、内存存储过多:
和内存一样,即使是本地存储,也不可能无限量的存储。我们需要做的就是当本地缓存满的时候,优先清除较老的数据。
是不是图片缓存觉得非常的麻烦,不过幸好图片加载的开源框架已经帮我们做好了,比如Glide。