android用if判断对象是否为空,RxJava(十)switchIfEmpty操作符实现Android检查本地缓存逻辑判断...

RxJava系列文章目录导读:

switchIfEmpty(Observable emptyObservable)操作符从字面意思上就很好理解,就是当为空的时候跳转到emptyObservable。

那么如何理解当为空的时候. 下面将会使用实际案例解释这个switchIfEmpty的使用方法。

一、业务需求

假如我们的app里有加载文章列表功能,要求加载的逻辑如下:加载文章的的时候,先从本地加载,如果本地存在就是用本地的数据,如果不存在从网络获取。

下面是业务代码:

//从本地数据获取文章列表

getArticlesObservable(pageIndex, pageSize, categoryId)

//本地不存在,请求api

.switchIfEmpty(articleApi.getArticlesByCategoryId(pageIndex + "", pageSize + "", categoryId + "")

.compose(this.handlerResult())

.flatMap(new Func1>() {

@Override

public Observable call(RespArticlePaginate respArticlePaginate) {

if (respArticlePaginate != null && respArticlePaginate.getList() != null) {

try {

articleDao.insertOrReplaceInTx(respArticlePaginate.getList());

} catch (Exception e) {

e.printStackTrace();

}

}

return Observable.just(respArticlePaginate);

}

}))

.subscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(createSubscriber(ID_ARTICLE_LIST)))

这里的 createSubscriber 封装了Subscriber对成功、失败的数据处理,然后统一把数据推给上一层,就不用每个地方都写下面相同的模板代码了:

observable.subscribe(new Action1() {

@Override

public void call(RespArticlePaginate respArticlePaginate) {

//success data

}

}, new Action1() {

@Override

public void call(Throwable throwable) {

// error data

}

})

那么createSubscriber是如何实现的,先看subscribe方法源码 如下:

public final Subscription subscribe(final Action1 super T> onNext, final Action1 onError) {

if (onNext == null) {

throw new IllegalArgumentException("onNext can not be null");

}

if (onError == null) {

throw new IllegalArgumentException("onError can not be null");

}

Action0 onCompleted = Actions.empty();

return subscribe(new ActionSubscriber(onNext, onError, onCompleted));

}

很简单,他是直接new了一个ActionSubscriber,然后把我们以前在代码里写的各个回调(onNext、onError、onComplete)当做参数传递进去。那么我们的createSubscriber也可以模拟它的实现:

/**

* 处理结果(分发结果) 封装

*

* @param id 区分业务类型

*/

protected ActionSubscriber createSubscriber(final int id) {

//因为我们只关心onNext和onError

Action0 onCompleted = Actions.empty();

return new ActionSubscriber(new Action1() {

@Override

public void call(T t) {

pushSuccessData(id, t);

}

}, new Action1() {

@Override

public void call(Throwable throwable) {

pushThrowable(id, throwable);

}

}, onCompleted);

}

好了,言归正传,回到我们上面提到的需求。根据需求我们来分析下代码:

getArticlesObservable方法用来从本地获取文章列表,articleApi.getArticlesByCategoryId方法是用来当本地不存在的时候从网络获取。似乎这些代码可以实现了我们上面提到的需求了。而且很简洁。

实践是检验真理的唯一标准,我们先运行下看看(本地环境是数据库没有文章列表)。

运行后,发现界面并没有展示数据,通过debug返现,代码执行了检测本地缓存的逻辑,且本地找不到符合逻辑的数据,也就是说从本地找到的结果为空。但是没有按照我们预想的是执行网络请求。

先来看看查询本地缓存的代码是是什么样子。

Observable.create(new Observable.OnSubscribe() {

@Override

public void call(Subscriber super Object> subscriber) {

try {

List as = articleDao.queryBuilder()

.where(ArticleDao.Properties.CategoryId.eq(categoryId))

.orderDesc(ArticleDao.Properties.Id)

.offset((pageIndex - 1) * pageSize)

.limit(pageSize).list();

if (as == null || as.isEmpty()) {

subscriber.onNext(null);

}else{

subscriber.onNext(as);

}

}catch (Exception e){

subscriber.onError(e);

}

subscriber.onCompleted();

}

});

通过debug发现代码走的逻辑是

if (as == null || as.isEmpty()) {

subscriber.onNext(null);

}

发送的是空,为什么还是没有走switchIfEmpty里的逻辑呢?肯定是我们用的姿势不对,先看看该该方法的说明:

/**

* Returns an Observable that emits the items emitted by the source Observable or the items of an alternate

* Observable if the source Observable is empty.

*

*

*

Scheduler:

*

{@code switchIfEmpty} does not operate by default on a particular {@link Scheduler}.

*

*

* @param alternate

* the alternate Observable to subscribe to if the source does not emit any items

* @return an Observable that emits the items emitted by the source Observable or the items of an

* alternate Observable if the source Observable is empty.

* @since 1.1.0

*/

public final Observable switchIfEmpty(Observable extends T> alternate) {

return lift(new OperatorSwitchIfEmpty(alternate));

}

重点关注对参数Observable extends T> alternate的解释:

the alternate Observable to subscribe to if the source does not emit any items

意思是如果原来的Observable没有发射任何数据(emit any items),则使用alternate代替原来的Observable。

好,再看看我们的代码逻辑:

if (as == null || as.isEmpty()) {

subscriber.onNext(null);

}

这段代码不是没有发射数据,而是发射了个空数据,也就是发射了null,所以这段代码并不是没有发射任何数据,所以为什么不走网络请求的逻辑。

知道原因就好解决了,加上个过滤就可以解决问题了:

.filter(new Func1() {

@Override

public Boolean call(RespArticlePaginate respArticlePaginate) {

return respArticlePaginate != null;

}

})

二、总结

1,通过switchIfEmpty可以做到一些逻辑判断,当然实现类型的判断本地缓存的,可以通过concat结合takeFirst操作符来实现,具体的可以看我以前的博客文章

2,上面通过Observable.create方式来包装数据查询,不是很优雅。下一篇博客介绍如何封装RxJava,使得我们的代码支持RxJava链式调用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值