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对成功、失败的数据处理,然后统1把数据推给上1层,就不用每一个地方都写下面相同的模板代码了:

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了1个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方法是用来当本地不存在的时候从网络获得。仿佛这些代码可以实现了我们上面提到的需求了。而且很简洁。

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

运行后,发现界面并没有展现数据,通过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可以做到1些逻辑判断,固然实现类型的判断本地缓存的,可以通过concat结合takeFirst操作符来实现,具体的可以看我之前的博客文章

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

java if or android_RxJava switchIfEmpty操作符实现Android检查本地缓存逻辑判断相关推荐

  1. Android -- ImageLoader本地缓存

    传送门 <Android -- ImageLoader简析>  http://www.cnblogs.com/yydcdut/p/4008097.html 本地缓存 在缓存文件时对文件名称 ...

  2. android+文件大小格式化,android 获取本地缓存文件大小,删除功能

    博客地址:http://blog.csdn.net/wwj_748/article/details/42737607 前言 本篇博客要给大家分享的如何获取应用缓存的大小和清除缓存的功能,我们知道我们应 ...

  3. JAVA 学到什么水平就可以转战 Android 了?

    田元 ,Android学习群:156562475,NONo笔记App作者 神兔兔.杨然.Kenkon Hu 等人赞同 先简单的分两种情况: 一.有编程基础,或者科班出身的,直接上吧.强烈推荐郭霖老师的 ...

  4. Caused by: java.lang.ClassNotFoundException: Didn't find class android.support.v4.view.ViewPager

    Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.v4.view.ViewPag ...

  5. java android长连接_基于Java Socket的自定义协议,实现Android与服务器的长连接(一)...

    一.基础知识准备 在正式给大家介绍自定义协议之前,我们先对网络传输和协议解析的相关知识点做一个基本的介绍,尽管这些知识点我们在学校里学过,但难免会有所遗忘,这里先做一个简单的介绍,以便对后文的内容理解 ...

  6. android java调用c_Android JNI简单实例(android 调用C/C++代码)

    Android的jni实例 android 的应用程序(Dalvik VM)中使用JNI(Java Native Interface)调用C/C++开发的共享库. c/c++中调用java程序的方法以 ...

  7. ios与java交互_5、与iOS、Android的交互 实践篇——主动调用

    本文属于「Unity与iOS.Android平台的整合」系列文章之一,转载请注明出处. 主要讲解Unity与iOS.Android平台相互主动调用实现 零.前言 由于本文涉及到较多基础知识,建议读者们 ...

  8. java里format报错,我的Android进阶之旅------Java字符串格式化方法String.format()格式化float型时小数点变成逗号问题...

    今天接到一个波兰的客户说有个APP在英文状态下一切运行正常,但是当系统语言切换到波兰语言的时候,程序奔溃了.好吧,又是我来维护. 好吧,先把系统语言切换到波兰语,切换到波兰语的方法查看文章 地址:ht ...

  9. java中的双冒号操作符

    java :: Java中的双冒号操作符 </h1><div class="clear"></div><div class="p ...

最新文章

  1. pl/sql 11g 12705_如何用PLSQL导出数据库存表结构信息
  2. 进行优化处理(WinXP),加快系统运行速度
  3. 工信部:鼓励采用低速直驱和高速直驱式永磁电机
  4. kernel: TCP: time wait bucket table overflow
  5. java arraystoreexception_java基础面试
  6. 【JS中innerHeight/Width、clientHeight/Width和offsetHeight/Width使用及其详解】
  7. maya中英文对照_玛雅中英文对照(全)
  8. 一个三非渣本的安卓秋招之路
  9. 投稿经验分享之二:国际EI会议(可检索)
  10. 什么才是状态机?什么又是状态?
  11. FIDE 全新编译体验,编译速度大幅提升
  12. 【C语言】#ifdef和#endif条件编译
  13. antlr + python
  14. Java字符串面试题
  15. 秘技·真·一键卸载JDK,刷新你的的世界观!
  16. [LeetCode][M0005]最长回文子串(Java)(马拉车(Manacher)算法)
  17. 简单的营销策略重复做,发挥到极致就是一心一意的去做
  18. Win10 OneNote 一直卡的登录界面
  19. 小傻蛋的妹妹跟随小甲鱼学习Python的第三节003
  20. 域服务器修复,重置 Windows 域目录还原(DRSM)密码

热门文章

  1. 随时随地以任意方式编写 .NET 应用程序
  2. 【送书活动】机器学习项目开发实战
  3. 为什么微软逐步转变为开源公司
  4. 教你实践ASP.NET Core Authorization(免看文档教程)
  5. Android 节操视频播放器jiecaovideoplayer自定义播放音频使用:屏蔽全屏按钮,增加倒计时,当前时间/总时间
  6. 【ArcGIS风暴】如何将矢量数据(点、线、面)折点坐标转为GeoJSON格式?
  7. 【GIS风暴】ArcGIS栅格重采样(Resample)方法详解
  8. windows执行python文件提示SyntaxError: Non-ASCII character ‘\xe9‘ in file 1.py on line 7, but no encoding d
  9. Android之jni解决JNIEnv跨线程问题
  10. linux之如何快速在文本里面写入内容