目录
RxJava操作符——创建操作符
在RxJava2极速入门系列的第一篇博文中讲到了RxJava的理念以及其基础知识,RxJava受到很多开发者的热爱,更在于其的强大的操作符能力,往往能将一个场景的Observable快速的转为另一个场景所适用的Observable。作为操作符详解开篇博文为博友附上常见分类如下:
吃瓜群众准备好了吗?一场创建操作符舞台剧现场开演,从示例到源码分析,一件件将它剖析出来:
先来看看创建操作符的分类:
create操作符
在官网中是这样描述这一操作符的:Create an Observable from scratch by means of a function.通过调用create函数将一个传统方式的Observable从头开始创建。其生命周期流程图如下:
从此可见,该生命周期执行其实是一一对应的。示例代码以及运行结果如下:
private fun operatorsCreate() {
showResultMessage("创建一个最基本的观察者模式")
logIMessage(
"operatorsCreate",
"""创建一个最基本的观察者模式""")
Observable.create<Long> {
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<Long> {
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 <T> Observable<T> create(ObservableOnSubscribe<T> source) {
ObjectHelper.requireNonNull(source, "source is null");
return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}
public interface ObservableOnSubscribe<T> {
/**
* Called for each Observer that subscribes.
* @param emitter the safe emitter instance, never null
* @throws Exception on error
*/
void subscribe(@NonNull ObservableEmitter<T> emitter) throws Exception;
}
在其底层源码是这样是实现的,先将其进行判空处理,然后再将其实例化的对象示例将其添加进去,由于其subscribe是可以被多个Obsever订阅的,所以每一次事件产生都会遍历其Observer的队列进行事件的分发,为了避免不相干的Observer都能接收事件分发,而增加的运算能力包裹多一层次的判断从而达到减少不必要的运算能力的事件分发。其实这种模式很常见,能够应用于大部分需要观察整个业务逻辑场景,但是面对只关注某写层次的业务逻辑处理的场景则显得代码冗余。
defer操作符
在官网中是这样描述这一操作符的: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 <T>
* 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 <T> Observable<T> defer(Callable<? extends ObservableSource<? extends T>> supplier) {
ObjectHelper.requireNonNull(supplier, "supplier is null");
return RxJavaPlugins.onAssembly(new ObservableDefer<T>(supplier));
}
public interface Callable<V> {
/**
* 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<T> {
/**
* 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已被创建浪费一些运算资源。
from操作符
官网中描述原话:convert various other objects and data types into Observables;从原话中可得:from可以将其他种类的对象和数据类型转换为Observable,from操作符的作用好在于,将需要处理的数据集合转换为一个Observables,然后通过统一的生命周期去管理每一项数据的发射与接收的。
fromArray操作符
该操作符是将一个数组进行数据遍历与发送,示例代码以及源码如下:
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 <T> Observable<T> 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<T>(items));
}
public static <T> Observable<T> empty() {
return RxJavaPlugins.onAssembly((Observable<T>) ObservableEmpty.INSTANCE);
}
@CheckReturnValue
@SchedulerSupport(Sched