目录
RxJava操作符——创建操作符
create操作符
defer操作符
from操作符
fromArray操作符
fromIterable操作符
fromFuture操作符
interval操作符
just操作符
range操作符
repeat操作符
repeat操作符分析
repeatWhen操作符
repeatUntil操作符
timer操作符
empty、never、error操作符
empty
never
error
总结
在RxJava2极速入门系列的第一篇博文中讲到了RxJava的理念以及其基础知识,RxJava受到很多开发者的热爱,更在于其的强大的操作符能力,往往能将一个场景的Observable快速的转为另一个场景所适用的Observable。作为操作符详解开篇博文为博友附上常见分类如下:
吃瓜群众准备好了吗?一场创建操作符舞台剧现场开演,从示例到源码分析,一件件将它剖析出来:
先来看看创建操作符的分类:
在官网中是这样描述这一操作符的:Create an Observable from scratch by means of a function.通过调用create函数将一个传统方式的Observable从头开始创建。其生命周期流程图如下:
从此可见,该生命周期执行其实是一一对应的。示例代码以及运行结果如下:
private fun operatorsCreate() {
showResultMessage("创建一个最基本的观察者模式")
logIMessage(
"operatorsCreate",
"""创建一个最基本的观察者模式""")
Observable.create {
if (!it.isDisposed) {
for (item in 1..10) {
it.onNext(item.toLong())
if (item == 10) it.onComplete()
}
}
}.observeOn(Schedulers.io()).subscribeOn(AndroidSchedulers.mainThread()).subscribe(object : Observer {
override fun onComplete() {
showResultMessage("onComplete")
logIMessage("operatorsCreate", "onComplete")
}
override fun onSubscribe(d: Disposable) {
showResultMessage("onSubscribe")
logIMessage("operatorsCreate", "onSubscribe")
}
override fun onNext(t: Long) {
showResultMessage("onNext-value$t")
logIMessage("operatorsCreate", "onNext-value$t")
}
override fun onError(e: Throwable) {
showResultMessage("onError${e.message ?: "unknown error"}")
logIMessage("operatorsCreate", "onError${e.message ?: "unknown error"}")
}
})
}
/**
* 运行结果如下:
* com.ypz.rxjavademo I/operatorsCreate: 创建一个最基本的观察者模式
* com.ypz.rxjavademo I/operatorsCreate: onSubscribe
* com.ypz.rxjavademo I/operatorsCreate: onNext-value1
* com.ypz.rxjavademo I/operatorsCreate: onNext-value2
* com.ypz.rxjavademo I/operatorsCreate: onNext-value3
* com.ypz.rxjavademo I/operatorsCreate: onNext-value4
* com.ypz.rxjavademo I/operatorsCreate: onNext-value5
* com.ypz.rxjavademo I/operatorsCreate: onNext-value6
* com.ypz.rxjavademo I/operatorsCreate: onNext-value7
* com.ypz.rxjavademo I/operatorsCreate: onNext-value8
* com.ypz.rxjavademo I/operatorsCreate: onNext-value9
* com.ypz.rxjavademo I/operatorsCreate: onNext-value10
* com.ypz.rxjavademo I/operatorsCreate: onComplete
*
* */
在create函数中了lambda表达式,其中使用到一个isDisposed去判断是否发送,达到了一个减小计算的压力的做法,这跟其底层源码有关,底层相关源码如下:
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static Observable create(ObservableOnSubscribe source) {
ObjectHelper.requireNonNull(source, "source is null");
return RxJavaPlugins.onAssembly(new ObservableCreate(source));
}
public interface ObservableOnSubscribe {
/**
* Called for each Observer that subscribes.
* @param emitter the safe emitter instance, never null
* @throws Exception on error
*/
void subscribe(@NonNull ObservableEmitter emitter) throws Exception;
}
在其底层源码是这样是实现的,先将其进行判空处理,然后再将其实例化的对象示例将其添加进去,由于其subscribe是可以被多个Obsever订阅的,所以每一次事件产生都会遍历其Observer的队列进行事件的分发,为了避免不相干的Observer都能接收事件分发,而增加的运算能力包裹多一层次的判断从而达到减少不必要的运算能力的事件分发。其实这种模式很常见,能够应用于大部分需要观察整个业务逻辑场景,但是面对只关注某写层次的业务逻辑处理的场景则显得代码冗余。
在官网中是这样描述这一操作符的:do not create the Observable until the observer subscribes, and create a fresh Observable for each observer.并不是一开就创建Observable直到订阅事件的产生并且为其每一个Obsever创建一个单独对应的Observable。也就是说defer操作符使用于一些延迟订阅或者懒加载获取最新数据队列的一些场景。其订阅流程如下:
在其流程图中可以很清晰的得出该操作符为每一个Observer单独创建一个Observable,示例代码以及运行结果如下:
/**
* 运行结果如下:
* com.ypz.rxjavademo I/Operators-Defer: sleep finsh
* com.ypz.rxjavademo I/Operators-Defer: was-create
* com.ypz.rxjavademo I/Operators-Defer: value:hello defer
*
* */
private fun operatorsDefer() {
//直到有观察者订阅时才创建 Observable,并且为每个观察者创建一个全新的Observable,
val defer = Observable.defer {
logIMessage("Operators-Defer","was-create")
Observable.just("hello defer")
}
Thread.sleep(2000)
logIMessage("Operators-Defer","sleep finsh")
defer.subscribe { logIMessage("Operators-Defer", "value:$it") }
}
defer函数其实就是当满足订阅被触发时候返回一个Observable其源码中是这样子写道:
/**
* Returns an Observable that calls an ObservableSource factory to create an ObservableSource for each new Observer
* that subscribes. That is, for each subscriber, the actual ObservableSource that subscriber observes is
* @param supplier
* the ObservableSource factory function to invoke for each {@link Observer} that subscribes to the
* resulting ObservableSource
* @param
* the type of the items emitted by the ObservableSource
* @return an Observable whose {@link Observer}s' subscriptions trigger an invocation of the given
* ObservableSource factory function
*/
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static Observable defer(Callable extends ObservableSource extends T>> supplier) {
ObjectHelper.requireNonNull(supplier, "supplier is null");
return RxJavaPlugins.onAssembly(new ObservableDefer(supplier));
}
public interface Callable {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
public interface ObservableSource {
/**
* Subscribes the given Observer to this ObservableSource instance.
* @param observer the Observer, not null
* @throws NullPointerException if {@code observer} is null
*/
void subscribe(@NonNull Observer super T> observer);
}
从源码注释以及源码中可以看出其实defer是使用个工厂设计模式去实现的,最终通过callable的事件为每一个Observer单独的返回一个Observable,尽管看似是订阅同一个Observable但本质是为了每一个Observer能够单独拥有一个数据序列。而且defer真正适用于一些懒加载实时获取最新数据的做法。
运用场景:使用defer可以实现懒加载方式,也就是lazy运算,并且通过lazy运算获取一些特定的值避免,没使用时,Observable已被创建浪费一些运算资源。
官网中描述原话:convert various other objects and data types into Observables;从原话中可得:from可以将其他种类的对象和数据类型转换为Observable,from操作符的作用好在于,将需要处理的数据集合转换为一个Observables,然后通过统一的生命周期去管理每一项数据的发射与接收的。
该操作符是将一个数组进行数据遍历与发送,示例代码以及源码如下:
Observable.fromArray("item1", 1).subscribe {logIMessage("fromArray", it.toString())}
/**
* 运行结果如下
* com.ypz.rxjavademo I/fromArray: item1
* com.ypz.rxjavademo I/fromArray: 1
* 源码如下:
* */
/**
* Converts an Array into an ObservableSource that emits the items in the Array.
*/
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static Observable fromArray(T... items) {
ObjectHelper.requireNonNull(items, "items is null");
if (items.length == 0) {
return empty();
} else
if (items.length == 1) {
return just(items[0]);
}
return RxJavaPlugins.onAssembly(new ObservableFromArray(items));
}
public static Observable empty() {
return RxJavaPlugins.onAssembly((Observable) ObservableEmpty.INSTANCE);
}
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static Observable just(T item) {
ObjectHelper.requireNonNull(item, "The item is null");
return RxJavaPlugins.onAssembly(new ObservableJust(item));
}
/**
* Represents a constant scalar value.
* @param the value type
*/
public final class ObservableJust extends Observable implements ScalarCallable {
private final T value;
public ObservableJust(final T value) {
this.value = value;
}
@Override
protected void subscribeActual(Observer super T> observer) {
ScalarDisposable sd = new ScalarDisposable(observer, value);
observer.onSubscribe(sd);
sd.run();
}
@Override
public T call() {
return value;
}
}
结合示例代码以及源码可以的得出其内部实现返回了三种不同类型Observable,当数组为Empty时候返回一个其内部实现的EmptyObservable来避免运行异常,而当数组长度仅仅为1的时候则返回角标位0所对应的Observable,有趣的是内部实现的ObservableFromArray这一个类,其实现了Observer通过其匿名类FromArrayDisposable中run方法判断每一个Observer是否处于订阅中处于则开始遍历发送数据确保每一个Observer都能接收Array中所有元素。
fromIterable操作符利用Iterable迭代器去实现对数据遍历,示例代码以及内部源码如下:
Observable.fromIterable(1..10).subscribe { logIMessage("fromIterable", it.toString())}
/**
* 运行结果如下
* com.ypz.rxjavademo I/fromIterable: 1
* com.ypz.rxjavademo I/fromIterable: 2
* com.ypz.rxjavademo I/fromIterable: 3
* com.ypz.rxjavademo I/fromIterable: 4
* com.ypz.rxjavademo I/fromIterable: 5
* com.ypz.rxjavademo I/fromIterable: 6
* com.ypz.rxjavademo I/fromIterable: 7
* com.ypz.rxjavademo I/fromIterable: 8
* com.ypz.rxjavademo I/fromIterable: 9
* com.ypz.rxjavademo I/fromIterable: 10
* 源码如下:
* */
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static Observable fromIterable(Iterable extends T> source) {
ObjectHelper.requireNonNull(source, "source is null");
return RxJavaPlugins.onAssembly(new ObservableFromIterable(source));
}
public final class ObservableFromIterable extends Observable {
final Iterable extends T> source;
public ObservableFromIterable(Iterable extends T> source) {
this.source = source;
}
/**
* Operator implementations (both source and intermediate) should implement this method that
* performs the necessary business logic and handles the incoming {@link Observer}s.
* There is no need to call any of the plugin hooks on the current {@code Observable} instance or
* the {@code Observer}; all hooks and basic safeguards have been
* applied by {@link #subscribe(Observer)} before this method gets called.
* @param observer the incoming Observer, never null
*/
@Override
public void subscribeActual(Observer super T> observer) {
Iterator extends T> it;
try {
it = source.iterator();
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
EmptyDisposable.error(e, observer);
return;
}
boolean hasNext;
try {
hasNext = it.hasNext();
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
EmptyDisposable.error(e, observer);
return;
}
if (!hasNext) {
EmptyDisposable.complete(observer);
return;
}
FromIterableDisposable d = new FromIterableDisposable(observer, it);
observer.onSubscribe(d);
if (!d.fusionMode) {
d.run();
}
}
}
结合示例代码以及运行结果可以得出fromIterable操作符利用Iterable去实现数据的迭代发送得益于其在subscribe前实现的subscribeActual,该方法在subscribe前运行,而FromIterableDisposable则是其内部实现的一个数据迭代Observer通过其内部run方法去实现其数据接收中牵涉的业务逻辑判断。
fomFuture操作符利用了Future这个类作为异步处理的观察者回调,这里简单解析下什么是Futer:Future模式,只是发起了耗时操作,函数立马就返回了,并不会阻塞客户端线程。所以在工作线程执行耗时操作的时候客户端无需等待,可以继续做其他事情,等到需要的时候再向工作线程获取结果。后面会单独写一篇博文介绍。对于fromFuture这个操作符最终会调用Futer.get()方法获取相应的数据回调并发射示例代码以及源码如下:
private fun fromFuture(){
val executorService = Executors.newCachedThreadPool()
val future = executorService.submit(Callable {
logIMessage("future", "do some work look like task")
Thread.sleep(2500)
"finsh work"
})
logIMessage("future", "do some work but it's timeout")
Observable.fromFuture(future, 1, TimeUnit.SECONDS).subscribe(
{
logIMessage("future-next", "value$it")
},
{
logIMessage("future-error", "value${it.message}")
}
)
Observable.fromFuture(future).subscribe {
logIMessage("future", "value$it")
}
}
/**
* 运行结果如下
* com.ypz.rxjavademo I/future: do some work but it's timeout
* com.ypz.rxjavademo I/future: do some work look like task
* com.ypz.rxjavademo I/future-error: valuenull
* com.ypz.rxjavademo I/future: valuefinsh work
* 源码如下:
* */
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static Observable fromFuture(Future extends T> future, long timeout, TimeUnit unit) {
ObjectHelper.requireNonNull(future, "future is null");
ObjectHelper.requireNonNull(unit, "unit is null");
return RxJavaPlugins.onAssembly(new ObservableFromFuture(future, timeout, unit));
}
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static Observable fromFuture(Future extends T> future) {
ObjectHelper.requireNonNull(future, "future is null");
return RxJavaPlugins.onAssembly(new ObservableFromFuture(future, 0L, null));
}
public final class ObservableFromFuture extends Observable {
final Future extends T> future;
final long timeout;
final TimeUnit unit;
public ObservableFromFuture(Future extends T> future, long timeout, TimeUnit unit) {
this.future = future;
this.timeout = timeout;
this.unit = unit;
}
@Override
public void subscribeActual(Observer super T> observer) {
DeferredScalarDisposable d = new DeferredScalarDisposable(observer);
observer.onSubscribe(d);
if (!d.isDisposed()) {
T v;
try {
v = ObjectHelper.requireNonNull(unit != null ? future.get(timeout, unit) : future.get(), "Future returned null");
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
if (!d.isDisposed()) {
observer.onError(ex);
}
return;
}
d.complete(v);
}
}
}
结合示例代码以及运行效果、源码,我们不难发现其结果回调时利用Future.get()这一方法去获取结果,在设置时间参数的fromFuture(Future extends T> future, long timeout, TimeUnit unit)这一方法中生成ObservableFromFuture这一对象利用超时机制去判断是否能够获得结果获得则进行onNext的传递否则进行onError的执行,而通过fromFuture(Future extends T> future)这一个机制而获得的ObservableFromFuture对象则是没有内部封装的超时机制完整执行了其内部Callback结果返回值决定执行哪种相应的事件传递的方法。
interval操作符create an Observable that emits a sequence of integers spaced by a given time interval可以看作一种整形序列的定时器的数据发送。作用流程如下:
在作用图中可以清晰的的出每一数据的发射,都是具有相同的时间间隔,interval其内部封装多种整形数列指定发送的形式下面则以其中一种实现方式示例代码以及结合源码进行讲解:
private fun operatorsInterval() {
/*类似定时器的作用*/
var disposable: Disposable? = null
var loadingArrayString = arrayOf("Loading", "Loading.", "Loading..", "Loading...", "Loading..", "Loading.")
logIMessage("Operators-interval", "实现动态修改字符串的值")
disposable = Observable.intervalRange(0, 6, 0, 1, TimeUnit.SECONDS)
.observeOn(Schedulers.io()).subscribeOn(AndroidSchedulers.mainThread()).subscribe {
val message = loadingArrayString[it.toInt()]
runOnUiThread { show_result.text = message }
logIMessage("Operators-interval-Loading", "value:$message")
if (it == 5L) disposable?.dispose()
}
}
/**
* 运行结果如下
* com.ypz.rxjavademo I/Operators-interval: 实现动态修改字符串的值
* com.ypz.rxjavademo I/Operators-interval-Loading: value:Loading
* com.ypz.rxjavademo I/Operators-interval-Loading: value:Loading.
* com.ypz.rxjavademo I/Operators-interval-Loading: value:Loading..
* com.ypz.rxjavademo I/Operators-interval-Loading: value:Loading...
* com.ypz.rxjavademo I/Operators-interval-Loading: value:Loading..
* com.ypz.rxjavademo I/Operators-interval-Loading: value:Loading.
* com.ypz.rxjavademo I/Operators-interval-Loading: value:Loading
* 源码如下:
* */
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
public static Observable interval(long initialDelay, long period, TimeUnit unit, Scheduler scheduler) {
ObjectHelper.requireNonNull(unit, "unit is null");
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
return RxJavaPlugins.onAssembly(new ObservableInterval(Math.max(0L, initialDelay), Math.max(0L, period), unit, scheduler));
}
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.COMPUTATION)
public static Observable interval(long period, TimeUnit unit) {
return interval(period, period, unit, Schedulers.computation());
} @CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
public static Observable interval(long period, TimeUnit unit, Scheduler scheduler) {
return interval(period, period, unit, scheduler);
}
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.COMPUTATION)
public static Observable intervalRange(long start, long count, long initialDelay, long period, TimeUnit unit) {
return intervalRange(start, count, initialDelay, period, unit, Schedulers.computation());
}
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
public static Observable intervalRange(long start, long count, long initialDelay, long period, TimeUnit unit, Scheduler scheduler) {
if (count < 0) {
throw new IllegalArgumentException("count >= 0 required but it was " + count);
}
if (count == 0L) {
return Observable.empty().delay(initialDelay, unit, scheduler);
}
long end = start + (count - 1);
if (start > 0 && end < 0) {
throw new IllegalArgumentException("Overflow! start + count is bigger than Long.MAX_VALUE");
}
ObjectHelper.requireNonNull(unit, "unit is null");
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
return RxJavaPlugins.onAssembly(new ObservableIntervalRange(start, end, Math.max(0L, initialDelay), Math.max(0L, period), unit, scheduler));
}
在示例代码中利用intervalRange(long start, long count, long initialDelay, long period, TimeUnit unit)这种方式达到一种定时器效果动态改变TextView的文字显示效果。interval(long initialDelay, long period, TimeUnit unit, Scheduler scheduler)这一个方法具体实现initialDelay指第一个数据发送延迟多少、period:之后每一个数据延迟多少发送、unit:时间格式单位、scheduler线程操作,而intervalRange是指定起始起始值并起始值之后执行的多少(n-1)个数字整形数列的定时发送。
just操作符:convert an object or a set of objects into an Observable that emits that or those objects,将一个对象或者多个对象看成一个可观测对象,逐一发射这些对象。just操作符底层是基于fromArray实现,但是在官网中已经描述的很清楚是一个可观测对象,逐一发射,just是将其看作一个有顺序(按传参方式顺序排序组合最多可支持10个)的队列的Observable。其流程图如下:
示例代码以及源码分析如下:
private fun operatorsJust() {
/*发射单数据*/
Observable.just("just").subscribe {
logIMessage("operatorsJust", it)
}
/*按顺序发射多数据*/
Observable.just(1, 2, 3, 4, "item5").subscribe {
logIMessage("operatorsJust2", it.toString())
}
}
/**
* 运行结果如下
* 03-23 08:28:54.788 15411-15411/com.ypz.rxjavademo I/operatorsJust: just
* com.ypz.rxjavademo I/operatorsJust2: 1
* com.ypz.rxjavademo I/operatorsJust2: 2
* com.ypz.rxjavademo I/operatorsJust2: 3
* com.ypz.rxjavademo I/operatorsJust2: 4
* com.ypz.rxjavademo I/operatorsJust2: item5
* 源码如下(以可支持最大参数组为例子):
* */
@SuppressWarnings("unchecked")
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static Observable just(T item1, T item2, T item3, T item4, T item5, T item6, T item7, T item8, T item9, T item10) {
ObjectHelper.requireNonNull(item1, "The first item is null");
ObjectHelper.requireNonNull(item2, "The second item is null");
ObjectHelper.requireNonNull(item3, "The third item is null");
ObjectHelper.requireNonNull(item4, "The fourth item is null");
ObjectHelper.requireNonNull(item5, "The fifth item is null");
ObjectHelper.requireNonNull(item6, "The sixth item is null");
ObjectHelper.requireNonNull(item7, "The seventh item is null");
ObjectHelper.requireNonNull(item8, "The eighth item is null");
ObjectHelper.requireNonNull(item9, "The ninth item is null");
ObjectHelper.requireNonNull(item10, "The tenth item is null");
return fromArray(item1, item2, item3, item4, item5, item6, item7, item8, item9, item10);
}
结合示例代码以及源码不难看出其实just就是基于fromArray实现的,其将fromArray实现返回的Observable原样返回,但是其对fromArray做多了一层封装,限制其可传参的数据长度以及调用fromArray前常规是判空处理。just与fromArray的最大区别在于再次封装,参数可选数量做限制以及其传参的判空处理的封装。
range操作符:create an Observable that emits a particular range of sequential integers,创建一个Observable将一个整形区间中每项数据发射出去。具体流程如下:
在range中start、count分别代码上面的n、m,range主要运用于整形数据区间的发送,在RxJava中range其思维还被用于intervalRange这个定时数据发射操作符中。示例代码以及源码如下:
private fun operatorsRange() {
Observable.range(1, 3).subscribe {
logIMessage("operators-range", it.toString())
}
}
/**
* 运行结果如下:
* com.ypz.rxjavademo I/operators-range: 1
* com.ypz.rxjavademo I/operators-range: 2
* com.ypz.rxjavademo I/operators-range: 3
* 源码分析如下:
* */
/**
* Returns an Observable that emits a sequence of Integers within a specified range.
* @param start
* the value of the first Integer in the sequence
* @param count
* the number of sequential Integers to generate
* @return an Observable that emits a range of sequential Integers
* @throws IllegalArgumentException
* if {@code count} is less than zero, or if {@code start} + {@code count} − 1 exceeds
* {@code Integer.MAX_VALUE}
*/
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static Observable range(final int start, final int count) {
if (count < 0) {
throw new IllegalArgumentException("count >= 0 required but it was " + count);
}
if (count == 0) {
return empty();
}
if (count == 1) {
return just(start);
}
if ((long)start + (count - 1) > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Integer overflow");
}
return RxJavaPlugins.onAssembly(new ObservableRange(start, count));
}
结合源码以及运行示例中可以的得出当count小于0是会出现异常、等于0则会返回empty,而等于1则利用just去实现返回,其次避免参数运行长度溢出还运用了Integer去进行判断,最终使用了ObservableRange去实现返回,range操作符还有rangeLong这一个操作符,其基于Long去实现,并且其支持的数值的范围更广。
repeat操作符:create an Observable that emits a particular item multiple times,repeat操作符可将一个或一组对象转换成为一个可观测的对象,并将这些对象创建多次并发送数据,可以特定中断等操作。
在示例图中可以得到repeat所观测的对象是多可以创建以及发送的接下来,示例代码以及运行结果分析:
private fun operatorsRepeat() {
logIMessage("Operators-repeat", "repeat 重复发送数据")
Observable.just("hello repeat").repeat(2).subscribe { logIMessage("Operators-repeat", "value:$it") }
logIMessage("Operators-repeat", "repeatWhen 指定条件重发数据或者中断数据")
Observable.create(
ObservableOnSubscribe { emitter ->
emitter.onNext("ss")
emitter.onComplete()
}).doOnComplete {
logIMessage("Operators-repeat-repeatWhen", "触发重订阅")
}.repeatWhen(object : Function, ObservableSource<*>> {
private var n = 0
@Throws(Exception::class)
override fun apply(objectObservable: Observable): ObservableSource<*> {
logIMessage("Operators-repeat-repeatWhen", "apply Times:$n")
return objectObservable.flatMap {
if (n != 3) {
logIMessage("Operators-repeat-repeatWhen", "flatMap Times:$n")
n++
Observable.timer(300, TimeUnit.MILLISECONDS)
} else {
Observable.empty()
}
}
}
}).subscribe(object : Observer {
override fun onSubscribe(d: Disposable) {}
override fun onNext(s: String) {
logIMessage("Operators-repeat-repeatWhen", "onNext:$s")
}
override fun onError(e: Throwable) {
logIMessage("Operators-repeat-repeatWhen", "onError:${e.message
?: "unknown error"}")
}
override fun onComplete() {
logIMessage("Operators-repeat-repeatWhen", "onComplete:")
}
})
Thread.sleep(2000)
logIMessage("Operators-repeat", "repeatUntil 达到条件就中断上流重复发送数据")
var repeatUntilTime = 0
Observable.interval(500, TimeUnit.MILLISECONDS).take(5).repeatUntil {
repeatUntilTime += 1
repeatUntilTime >= 2
}.subscribe {
logIMessage("Operators-repeat-repeatUntil", "value$it")
}
}
/**
* 运行结果如下:
* com.ypz.rxjavademo I/Operators-repeat: repeat 重复发送数据
* com.ypz.rxjavademo I/Operators-repeat: value:hello repeat
* com.ypz.rxjavademo I/Operators-repeat: value:hello repeat
* com.ypz.rxjavademo I/Operators-repeat: repeatWhen 指定条件重发数据或者中断数据
* com.ypz.rxjavademo I/Operators-repeat-repeatWhen: apply Times:0
* com.ypz.rxjavademo I/Operators-repeat-repeatWhen: onNext:ss
* com.ypz.rxjavademo I/Operators-repeat-repeatWhen: 触发重订阅
* com.ypz.rxjavademo I/Operators-repeat-repeatWhen: flatMap Times:0
* com.ypz.rxjavademo I/Operators-repeat-repeatWhen: onNext:ss
* com.ypz.rxjavademo I/Operators-repeat-repeatWhen: 触发重订阅
* com.ypz.rxjavademo I/Operators-repeat-repeatWhen: flatMap Times:1
* com.ypz.rxjavademo I/Operators-repeat-repeatWhen: onNext:ss
* com.ypz.rxjavademo I/Operators-repeat-repeatWhen: 触发重订阅
* com.ypz.rxjavademo I/Operators-repeat-repeatWhen: flatMap Times:2
* com.ypz.rxjavademo I/Operators-repeat-repeatWhen: onNext:ss
* com.ypz.rxjavademo I/Operators-repeat-repeatWhen: 触发重订阅
* com.ypz.rxjavademo I/Operators-repeat: repeatUntil 达到条件就中断上流重复发送数据
* com.ypz.rxjavademo I/Choreographer: Skipped 121 frames! The application may be doing too much work on its main thread.
* com.ypz.rxjavademo I/Operators-repeat-repeatUntil: value0
* com.ypz.rxjavademo I/Operators-repeat-repeatUntil: value1
* com.ypz.rxjavademo I/Operators-repeat-repeatUntil: value2
* com.ypz.rxjavademo I/Operators-repeat-repeatUntil: value3
* com.ypz.rxjavademo I/Operators-repeat-repeatUntil: value4
* com.ypz.rxjavademo I/Operators-repeat-repeatUntil: value0
* com.ypz.rxjavademo I/Operators-repeat-repeatUntil: value1
* com.ypz.rxjavademo I/Operators-repeat-repeatUntil: value2
* com.ypz.rxjavademo I/Operators-repeat-repeatUntil: value3
* com.ypz.rxjavademo I/Operators-repeat-repeatUntil: value4
* */
在示例代码以及运行结果中可以得出repeat重复创建以及发送数据为两次,与repeat(n)中n的有关,创建次数为n次。以源码为例子:
/**
* Returns an Observable that repeats the sequence of items emitted by the source ObservableSource at most
* {@code count} times.
*
* @param times
* the number of times the source ObservableSource items are repeated, a count of 0 will yield an empty
* sequence
* @return an Observable that repeats the sequence of items emitted by the source ObservableSource at most
* {@code count} times
* @throws IllegalArgumentException
* if {@code count} is less than zero
* @see ReactiveX operators documentation: Repeat
*/
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final Observable repeat(long times) {
if (times < 0) {
throw new IllegalArgumentException("times >= 0 required but it was " + times);
}
if (times == 0) {
return empty();
}
return RxJavaPlugins.onAssembly(new ObservableRepeat(this, times));
public final class ObservableRepeat extends AbstractObservableWithUpstream {
final long count;
public ObservableRepeat(Observable source, long count) {
super(source);
this.count = count;
}
@Override
public void subscribeActual(Observer super T> observer) {
SequentialDisposable sd = new SequentialDisposable();
observer.onSubscribe(sd);
RepeatObserver rs = new RepeatObserver(observer, count != Long.MAX_VALUE ? count - 1 : Long.MAX_VALUE, sd, source);
rs.subscribeNext();
}
static final class RepeatObserver extends AtomicInteger implements Observer {
private static final long serialVersionUID = -7098360935104053232L;
final Observer super T> downstream;
final SequentialDisposable sd;
final ObservableSource extends T> source;
long remaining;
RepeatObserver(Observer super T> actual, long count, SequentialDisposable sd, ObservableSource extends T> source) {
this.downstream = actual;
this.sd = sd;
this.source = source;
this.remaining = count;
}
@Override
public void onComplete() {
long r = remaining;
if (r != Long.MAX_VALUE) {
remaining = r - 1;
}
if (r != 0L) {
subscribeNext();
} else {
downstream.onComplete();
}
}
/**
* Subscribes to the source again via trampolining.
*/
void subscribeNext() {
if (getAndIncrement() == 0) {
int missed = 1;
for (;;) {
if (sd.isDisposed()) {
return;
}
source.subscribe(this);
missed = addAndGet(-missed);
if (missed == 0) {
break;
}
}
}
}
}
}
从源码中我们不难发现,其关键在于ObservableRepeat以及SequentialDisposable的实现,通过ObservableRepeat通过订阅时触发subscribeActual,然后Next、Complete这两个时间触发的时候去实现其相关重复发送数据业务逻辑判断。以此达到重复创建发送数据的效果。
这是RxJava2.X新增的操作符,其目的在于观测数据发送期间是否可以判定某些条件重发数据或者中断数据的发射等操作,结合示例代码以及运行结果可以看出,当触发订阅达到3次后终止重新发送数据,需要注意一点:说法没有错但是repeatWhen在使用完整个事件流创建的时候它会一并创建出来而且只会创建一次并不是在上游调用onComple后才会回调到这个事件,这个事件创建了决定是否重复以及终止数据被观察着对象仅仅回调一次。源码如下:
public final Observable repeatWhen(final Function super Observable
在部分源码截图中可以的出这一操作符最为核心的是ObservableRepeatWhen以及Function这两个的实现,通过其内部ObservableRepeatWhen的实现最后调用Function的实现来达到发送数据过程中这一观测效果。
repeatUntil也是RxJava2.X新增的操作符,其作用用于观测上游数据发送达到某一个峰值的时候中断数据的发送避免数据发送过多的资源以此达到避免造成计算资源浪费的效果。结合示例代码可以很轻易的看到当重复发送数据到达两次时则中断数据发送。
源码如下:
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final Observable repeatUntil(BooleanSupplier stop) {
ObjectHelper.requireNonNull(stop, "stop is null");
return RxJavaPlugins.onAssembly(new ObservableRepeatUntil(this, stop));
}
/**
* A functional interface (callback) that returns a boolean value.
*/
public interface BooleanSupplier {
/**
* Returns a boolean value.
* @return a boolean value
* @throws Exception on error
*/
boolean getAsBoolean() throws Exception; // NOPMD
}
不难看出其核心就是ObservableRepeatUntil、BooleanSupplier这两个的实现。通过实现其BooleanSupplier实现其是否中断数据的条件,然后再通过其内部实现的ObservableRepeatUntil这个类进行创建调用以此达到这一效果
timer:create an Observable that emits a particular item after a given delay,一个具有起始延迟发送数据的操作符。timer操作符常用于起始延迟发送数据,避免一开始数据就发送导致一开始订阅就要接收处理的线程异步问题,常用与一些异步回调线程小阻塞等。
结合示例代码以及源码分析:
private fun operatorsTimer() {
/*指定一段时间延迟开始发送数据*/
logIMessage("", "延迟两秒发送数据")
showResultMessage("延迟两秒发送数据")
Observable.timer(2, TimeUnit.SECONDS).observeOn(Schedulers.io()).subscribeOn(AndroidSchedulers.mainThread()).subscribe {
logIMessage("Operators-interval-Loading", "value:hello timer")
showResultMessage("hello timer")
}
}
/**
* 运行结果如下:
* com.ypz.rxjavademo I/Operators-timer: 延迟两秒发送数据
* com.ypz.rxjavademo I/Operators-timer: value:hello timer
* */
/**
* Returns an Observable that emits {@code 0L} after a specified delay, and then completes.
*
* @param delay
* the initial delay before emitting a single {@code 0L}
* @param unit
* time units to use for {@code delay}
* @return an Observable that {@code 0L} after a specified delay, and then completes
* @see ReactiveX operators documentation: Timer
*/
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.COMPUTATION)
public static Observable timer(long delay, TimeUnit unit) {
return timer(delay, unit, Schedulers.computation());
}
结合运行结果可以得出起始timer的实现就是得益于Schedulers.computation()这一方法。运用场景可以利用两个Observable实现防止双点击效果具体代码如下:
private fun doubleClick(view: View, time: Long, unClickTimeUnit: TimeUnit, comitToDo: () -> Unit) {
if (!view.isClickable) return
else {
view.isClickable = false
comitToDo()
Observable.timer(time, unClickTimeUnit).observeOn(Schedulers.io()).subscribeOn(AndroidSchedulers.mainThread()).subscribe {
runOnUiThread {
view.isClickable = true
}
}
}
}
empty:create an Observable that emits no items but terminates normally,创建一个没有任何发射数据Observable并且正常终止;
示例代码如下:
Observable.empty().subscribe(object :Observer{
override fun onComplete() {
logIMessage("Operators-empty","value:onComplete")
}
override fun onSubscribe(d: Disposable) {
}
override fun onNext(t: String) {
logIMessage("Operators-empty","value:$it")
}
override fun onError(e: Throwable) {
logIMessage("Operators-empty","value:$it")
}
})
/**
* 运行结果如下:
* com.ypz.rxjavademo I/Operators-empty: value:onComplete
* */
Empty只适用不需要住任何操作仅仅只需要成功的回调的创建。
never:create an Observable that emits no items and does not terminate,创建一个不发射数据也不终止的Observable
示例代码如下:
Observable.never().subscribe(object :Observer{
override fun onComplete() {
logIMessage("Operators-never","value:onComplete")
}
override fun onSubscribe(d: Disposable) {
logIMessage("Operators-never","value:onSubscribe")
}
override fun onNext(t: String) {
logIMessage("Operators-never","value:$it")
}
override fun onError(e: Throwable) {
logIMessage("Operators-never","value:$it")
}
})
/**
* 运行结果如下:
* com.ypz.rxjavademo I/Operators-never: value:onSubscribe
* */
可以看出never只有订阅的回调并不会触发事件的分发以及错误,结束等回调。
error:create an Observable that emits no items and terminates with an error,创建一个不发射数据以一个错误终止的Observable 。
示例代码如下:
Observable.error {
Throwable("this is a error")
}.subscribe(object :Observer{
override fun onComplete() {
logIMessage("Operators-error","value:onComplete")
}
override fun onSubscribe(d: Disposable) {
logIMessage("Operators-error","value:onSubscribe")
}
override fun onNext(t: Throwable) {
logIMessage("Operators-error","onNext value:$it")
}
override fun onError(e: Throwable) {
logIMessage("Operators-error","onError value:$it")
}
})
/**
* 运行结果如下:
* com.ypz.rxjavademo I/Operators-error: value:onSubscribe
* com.ypz.rxjavademo I/Operators-error: onError value:10
*
* */
可以看出出了onSubscribe和error被触发外其余都没有被触发。
create:适用于大部分场景可以监测到,并且针对每一个需要监听事件发送以及接收都能很好的处理。注意要添加判断避免事件无用分发导致运算能力的浪费
defer:适用于lazy运算的方式避免一创建就马上执行。
from:适用于多个数据类型的组合为一个对象的发送。
interval:适用于类似定时器数据发送。注意是整形数据。
just:适用于一个或多个对象的组合发送基于fromArray实现。
range:发射一个整形区间注意开闭区间,按顺序发送数据。
repeat:用于重复发送数据或者观测数据是否重复发送或者中断发送。
timer:延迟发送数据作用。
Empty:只做完成的动作。
error:只发送错误的作用
never:绝不发送数据的作用。
代码点我传送