目录
RxJava入门理念
传统异步式编程解决繁琐的面对对象编程往往采用抽象的对象关系这种做法处理异步事件,往往在并发中处理异步式的事务必要实现不少的抽象对象用以具体解决这些异步式事务所期望的结果。导致了代码的维护效果过于冗重。
Rx是一个编程模型,目标是提供一致的编程接口,帮助开发者更方便地处理异数据流。RxJava充分体现函数响应式编程思维,解决编写传统的异步代码过于繁琐的痛点,采用函数式的方式使得代码更好维护以及编写。
函数响应式编程的概念及特点
函数响应式编程结合函数式及响应式优点用以解决传统的面向对象的抽象关系,响应式编程通过函数式编程的方式用以解决传统的Callback回调问题。
函数编程概念
面对越来越复杂的并发编程及分布式处理、多线程中常见的死锁、线程饥饿、竞争条件等问题,由于多线程并不像单线程那样单一而简单的定位程序BUG,往往看似毫无问题单线程编程任务在运行多线程中由于一些没有注意到的地方导致程序运行严重至奔溃线程无法调度严重堵塞等问题,其BUG也由于多种不可预料的条件而诞生往往难以复现及定位。
而函数式编程往往由于其数据不可变,因而没有其并发编程中问题,相对于并发编程它更较于安全,函数式编程可以将解决个问题的业务逻辑单独的看出是函数的求解,在其求解过程中,常常可运用于单一原则多次复用某一函数,同时并避免了状态以及变量的概念,思维更接近与数学运算。
函数编程特性
响应式编程概念
响应式编程是一种面向数据流及变化传播的编程方式,意味着静态以及动态的数据流可以很直观被表达展示,而其相关的计算的数学模型会将变化的值直接以数据流的方式进行传播。
响应式编程的特性
RxJava的基础知识
RxJava遵循Reactive Extensions原则基于JVM平台上的一种实现,通过使用观察着序列构建异步、基于事件的程序。基于观察者设计模式一种拓展,支持不同的数据、事件流以及额外的操作类,允许通过声明式方式构建不同的执行序列,使用抽象的方式去屏蔽底层中多线程、同步、线程安全、并发数据结构、非阻塞IO等逻辑实现,其次还支持Java1.5及之后版本,以及其基于JVM开发的各种语言。稍后的代码示例以Kotlin为主。
RxJava的创建
RxJava的使用通常分为三部曲:
创建Observable(被观察者),它会决定什么时候触发事件以及触发怎么样的事件,也就是当你想程序执行到某一种条件的时候,你想处理的异步操作顺序以及操作次数都可以由它来决定。
创建Observer(观察者),它代表着不同的线程中执行异步处理事件业务逻辑回调都在里面去做操作,观察者在未执行的时候它永远待命的哨兵,举个例子:它就像一个阻击手,一直待命隐蔽藏在一个角落中,直到目标(被观察者)出现(程序所需要执行的异步条件的)阻击目标(执行你所期待的异步事件逻辑)。
使用subscribe()两者间进行订阅,这就好比阻击手有了,目标有了但是还得告诉阻击手你阻击的任务对象是谁你要在哪个地方去阻击他,这就是subscribe()方法实现所做的事情。
接下来看一下代码示例:
/**
* error or next
* onComplete
* */
private fun createExample() {
Observable
.just("this is create Demo")
.subscribe(
{ logIMessage("createExample", "msg:$it") },
{ logIMessage("createExample", "error:${it.message ?: "unkown Error"}") },
{ logIMessage("createExample", "onComplete") }
)
}
/**
* subscribe
* error or next
* onComplete
* */
private fun createExample2() {
Observable
.just("this is create Demo")
.subscribe(
{ logIMessage("createExample2", "msg:$it") },
{ logIMessage("createExample2", "error:${it.message ?: "unkown Error"}") },
{ logIMessage("createExample2", "onComplete") },
{ logIMessage("createExample2", "subscribe") }
)
}
利用just()方法创建一个Observable<String>类型的再通过subscribe()方法链式的将观察者绑定在一起。接下来我们追踪源码看看它做了啥。
/**
* @param item
* the item to emit
* @param <T>
* the type of that item
* @return an Observable that emits {@code value} as a single item and then completes
* @see <a href="http://reactivex.io/documentation/operators/just.html">ReactiveX operators documentation: Just</a>
* @see #just(Object, Object)
* @see #fromCallable(Callable)
* @see #fromArray(Object...)
* @see #fromIterable(Iterable)
*/
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static <T> Observable<T> just(T item) {
ObjectHelper.requireNonNull(item, "The item is null");
return RxJavaPlugins.onAssembly(new ObservableJust<T>(item));
}
/**
* Verifies if the object is not null and returns it or throws a NullPointerException
* with the given message.
* @param <T> the value type
* @param object the object to verify
* @param message the message to use with the NullPointerException
* @return the object itself
* @throws NullPointerException if object is null
*/
public static <T> T requireNonNull(T object, String message) {
if (object == null) {
throw new NullPointerException(message);
}
return object;
}
/**
* Calls the associated hook function.
* @param <T> the value type
* @param source the hook's input value
* @return the value returned by the hook
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@NonNull
public static <T> Observable<T> onAssembly(@NonNull Observable<T> source) {
Function<? super Observable, ? extends Observable> f = onObservableAssembly;
if (f != null) {
return apply(f, source);
}
return source;
}
在源码中我们可以很清晰的看到T是一个泛型,通过使用内部封装的ObjectHelper去判断我们传入的泛型是否为空,用以避免我们创建这样一个Obserable<Null>被观察者,其次在利用RxJavaPlugins.onAssembly()这一个方法去将一个hook Function关联的一个被观察者创建出来,这里做了一个很有意思的事情,首先拿自身的一个Function用来判断是否是一个空的对象,如果不是调用自身的apply方法将其添加我们创建的被观察者然后返回给我们,如果为空就直接返回自身。为什么要通过使用apply呢?其实跟接下来的源码分析都有关系,通过使用apply讲他们的source相关的操作链接在一起,如果你实现了那些方法或者需要那些回调的时候通过判断回调去做你那些需要做的东西,当然如果你没有实现的话他做自己那默认的一套东西。
接下来我们以createExample2()方法中去查阅下subscribe中它究竟干了些啥?
/**
* Subscribes to an ObservableSource and provides callbacks to handle the items it emits and any error or
* completion notification it issues.
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code subscribe} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
*
* @param onNext
* the {@code Consumer<T>} you have designed to accept emissions from the ObservableSource
* @param onError
* the {@code Consumer<Throwable>} you have designed to accept any error notification from the
* ObservableSource
* @param onComplete
*