RxJava2 源代码解析(一)
转载请标明出处:
http://blog.csdn.net/zxt0601/article/details/61614799
本文出自:【张旭童的博客】(http://blog.csdn.net/zxt0601)
概述
近期事情太多了,如今公司内部的变动,自己岗位的变化,以及近期决定找工作。
所以博客耽误了。准备面试中,打算看一看RxJava2的源代码。遂有了这篇文章。
不会对RxJava2的源代码逐字逐句的阅读,仅仅寻找关键处,我们平时接触得到的那些代码。
背压实际中接触较少。故仅仅分析了Observable
.
分析的源代码版本号为:2.0.1
我们的目的:
- 知道源头(
Observable
)是怎样将数据发送出去的。 - 知道终点(
Observer
)是怎样接收到数据的。 - 何时将源头和终点关联起来的
- 知道线程调度是怎么实现的
- 知道操作符是怎么实现的
本文先达到目的1 。2 ,3。
我个人觉得主要还是适配器模式的体现,我们接触的就仅仅有Observable
和Observer
,事实上内部有大量的中间对象在适配:将它们两联系起来。增加一些额外功能,比如考虑dispose和hook等。
从create開始。
这是一段不涉及操作符和线程切换的简单样例:
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
e.onNext("1");
e.onComplete();
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe() called with: d = [" + d + "]");
}
@Override
public void onNext(String value) {
Log.d(TAG, "onNext() called with: value = [" + value + "]");
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError() called with: e = [" + e + "]");
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete() called");
}
});
拿 create来说。
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
//.....
return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}
返回值是Observable
,參数是ObservableOnSubscribe
,定义例如以下:
public interface ObservableOnSubscribe<T> {
void subscribe(ObservableEmitter<T> e) throws Exception;
}
ObservableOnSubscribe
是一个接口。里面就一个方法,也是我们实现的那个方法:
该方法的參数是 ObservableEmitter
。我觉得它是关联起 Disposable
概念的一层:
public interface ObservableEmitter<T> extends Emitter<T> {
void setDisposable(Disposable d);
void setCancellable(Cancellable c);
boolean isDisposed();
ObservableEmitter<T> serialize();
}
ObservableEmitter
也是一个接口。里面方法非常多,它也继承了 Emitter<T>
接口。
public interface Emitter<T> {
void onNext(T value);
void onError(Throwable error);
void onComplete();
}
Emitter<T>
定义了 我们在ObservableOnSubscribe
中实现subscribe()
方法里最经常使用的三个方法。
好,我们回到原点。create()
方法里就一句话return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
,当中提到RxJavaPlugins.onAssembly()
:
/**
* 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" })
public static <T> Observable<T> onAssembly(Observable<T> source) {
Function<Observable, Observable> f = onObservableAssembly;
if (f != null) {
return apply(f, source);
}
return source;
}
能够看到这是一个关于hook的方法。关于hook我们暂且不表,不影响主流程。我们默认使用中都没有hook,所以这里就是直接返回source
,即传入的对象。也就是new ObservableCreate<T>(source)
.
ObservableCreate
我觉得算是一种适配器的体现,create()
须要返回的是Observable
,而我如今有的是(方法传入的是)ObservableOnSubscribe
对象,ObservableCreate
将ObservableOnSubscribe
适配成Observable
。
当中subscribeActual()
方法表示的是被订阅时真正被运行的方法,放后面解析:
public final class ObservableCreate<T> extends Observable<T> {
final ObservableOnSubscribe<T> source;
public ObservableCreate(ObservableOnSubscribe<T> source) {
this.source = source;
}
@Override
protected void subscribeActual(Observer<?
super T> observer) {
CreateEmitter<T> parent = new CreateEmitter<T>(observer);
observer.onSubscribe(parent);
try {
source.subscribe(parent);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);
}
}
OK,至此。创建流程结束,我们得到了Observable<T>
对象。事实上就是ObservableCreate<T>
.
到订阅subscribe 结束
subscribe()
:
public final void subscribe(Observer<?
super T> observer) {
...
try {
//1 hook相关,略过
observer = RxJavaPlugins.onSubscribe(this, observer);
...
//2 真正的订阅处
subscribeActual(observer);
} catch (NullPointerException e) { // NOPMD
throw e;
} catch (Throwable e) {
//3 错误处理,
Exceptions.throwIfFatal(e);
// can't call onError because no way to know if a Disposable has been set or not
// can't call onSubscribe because the call might have set a Subscription already
//4 hook错误相关,略过
RxJavaPlugins.onError(e);
NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
npe.initCause(e);
throw npe;
}
}
关于hook的代码:
能够看到假设没有hook。即对应的对象是null。则是传入什么返回什么的。
/**
* Calls the associated hook function.
* @param <T> the value type
* @param source the hook's input value
* @param observer the observer
* @return the value returned by the hook
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static <T> Observer<? super T> onSubscribe(Observable<T> source, Observer<?
super T> observer) {
//1 默认onObservableSubscribe(可理解为一个flatmap的操作)是null
BiFunction<Observable, Observer, Observer> f = onObservableSubscribe;
//2 所以这句跳过,不会对其进行apply
if (f != null) {
return apply(f, source, observer);
}
//3 返回參数2
return observer;
}
我也是验证了一下 三个Hook相关的变量。确实是null:
Consumer<Throwable> errorHandler = RxJavaPlugins.getErrorHandler();
BiFunction<Observable, Observer, Observer> onObservableSubscribe = RxJavaPlugins.getOnObservableSubscribe();
Function<Observable, Observable> onObservableAssembly = RxJavaPlugins.getOnObservableAssembly();
Log.e(TAG, "errorHandler = [" + errorHandler + "]");
Log.e(TAG, "onObservableSubscribe = [" + onObservableSubscribe + "]");
Log.e(TAG, "onObservableAssembly = [" + onObservableAssembly + "]");
所以订阅时的重点就是:
//2 真正的订阅处
subscribeActual(observer);
我们将第一节提到的ObservableCreate
里的subscribeActual()
方法拿出来看看:
@Override
protected void subscribeActual(Observer<? super T> observer) {
//1 创建CreateEmitter,也是一个适配器
CreateEmitter<T> parent = new CreateEmitter<T>(observer);
//2 onSubscribe()參数是Disposable ,所以CreateEmitter能够将Observer->Disposable 。另一点要注意的是`onSubscribe()`是在我们运行`subscribe()`这句代码的那个线程回调的。并不受线程调度影响。
observer.onSubscribe(parent);
try {
//3 将ObservableOnSubscribe(源头)与CreateEmitter(Observer,终点)联系起来
source.subscribe(parent);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
//4 错误回调
parent.onError(ex);
}
}
Observer
是一个接口。里面就四个方法,我们在开头的样例中已经所有实现(打印Log)。
public interface Observer<T> {
void onSubscribe(Disposable d);
void onNext(T value);
void onError(Throwable e);
void onComplete();
}
重点在这一句:
//3 将ObservableOnSubscribe(源头)与CreateEmitter(Observer,终点)联系起来
source.subscribe(parent);
source
即ObservableOnSubscribe
对象。在本文中是:
new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
e.onNext("1");
e.onComplete();
}
}
则会调用parent.onNext()
和parent.onComplete()
。parent
是CreateEmitter
对象,例如以下:
static final class CreateEmitter<T>
extends AtomicReference<Disposable>
implements ObservableEmitter<T>, Disposable {
final Observer<?
super T> observer;
CreateEmitter(Observer<? super T> observer) {
this.observer = observer;
}
@Override
public void onNext(T t) {
...
//假设没有被dispose。会调用Observer的onNext()方法
if (!isDisposed()) {
observer.onNext(t);
}
}
@Override
public void onError(Throwable t) {
...
//1 假设没有被dispose。会调用Observer的onError()方法
if (!isDisposed()) {
try {
observer.onError(t);
} finally {
//2 一定会自己主动dispose()
dispose();
}
} else {
//3 假设已经被dispose了。会抛出异常。
所以onError、onComplete彼此相互排斥。仅仅能被调用一次
RxJavaPlugins.onError(t);
}
}
@Override
public void onComplete() {
//1 假设没有被dispose,会调用Observer的onComplete()方法
if (!isDisposed()) {
try {
observer.onComplete();
} finally {
//2 一定会自己主动dispose()
dispose();
}
}
}
@Override
public void dispose() {
DisposableHelper.dispose(this);
}
@Override
public boolean isDisposed() {
return DisposableHelper.isDisposed(get());
}
}
总结重点:
Observable
和Observer
的关系没有被dispose
。才会回调Observer
的onXXXX()
方法Observer
的onComplete()
和onError()
相互排斥仅仅能运行一次。由于CreateEmitter
在回调他们两中随意一个后。都会自己主动dispose()
。依据第一点,验证此结论。
Observable
和Observer
关联时(订阅时)。Observable
才会開始发送数据。ObservableCreate
将ObservableOnSubscribe
(真正的源)->Observable
.ObservableOnSubscribe
(真正的源)须要的是发射器ObservableEmitter
.CreateEmitter
将Observer
->ObservableEmitter
,同一时候它也是Disposable
.- 先
error
后complete
。complete
不显示。 反之会crash。感兴趣的能够写例如以下代码验证。
e.onNext("1");
//先error后complete,complete不显示。
反之 会crash
//e.onError(new IOException("sb error"));
e.onComplete();
e.onError(new IOException("sb error"));
一个好玩的地方DisposableHelper
原本到这里,最简单的一个流程我们算是搞清了。
还值得一提的是,DisposableHelper.dispose(this);
DisposableHelper
非常有趣。它是一个枚举,这是利用枚举实现了一个单例disposed state
,即是否disposed,假设Disposable
类型的变量的引用等于DISPOSED
,则起点和终点已经断开联系。
当中大多数方法 都是静态方法,所以isDisposed()
方法的实现就非常easy。直接比較引用就可以.
其它的几个方法。和AtomicReference
类搅基在了一起。
这是一个实现引用原子操作的类,对象引用的原子更新
。经常用法例如以下:
//返回当前的引用。
V get()
//假设当前值与给定的expect引用相等,(注意是引用相等而不是equals()相等),更新为指定的update值。
boolean compareAndSet(V expect, V update)
//原子地设为给定值并返回旧值。
V getAndSet(V newValue)
OK,铺垫完了我们看看源代码吧:
public enum DisposableHelper implements Disposable {
/**
* The singleton instance representing a terminal, disposed state, don't leak it.
*/
DISPOSED
;
public static boolean isDisposed(Disposable d) {
return d == DISPOSED;
}
public static boolean dispose(AtomicReference<Disposable> field) {
//1 通过断点查看,默认情况下,field的值是"null",并不是引用是null哦!大坑大坑大坑
//可是current是null引用
Disposable current = field.get();
Disposable d = DISPOSED;
//2 null不等于DISPOSED
if (current != d) {
//3 field是DISPOSED了,current还是null
current = field.getAndSet(d);
if (current != d) {
//4 默认情况下 走不到这里,这里是在设置了setCancellable()后会走到。
if (current != null) {
current.dispose();
}
return true;
}
}
return false;
}
总结
- 在
subscribeActual()
方法中。源头和终点关联起来。 source.subscribe(parent);
这句代码运行时,才開始从发送ObservableOnSubscribe
中利用ObservableEmitter
发送数据给Observer
。即数据是从源头push给终点的。CreateEmitter
中,仅仅有Observable
和Observer
的关系没有被dispose
,才会回调Observer
的onXXXX()
方法Observer
的onComplete()
和onError()
相互排斥仅仅能运行一次,由于CreateEmitter
在回调他们两中随意一个后。都会自己主动dispose()
。依据上一点,验证此结论。
- 先
error
后complete
,complete
不显示。 反之会crash - 另一点要注意的是
onSubscribe()
是在我们运行subscribe()
这句代码的那个线程回调的。并不受线程调度影响。
转载请标明出处:
http://blog.csdn.net/zxt0601/article/details/61614799
本文出自:【张旭童的博客】(http://blog.csdn.net/zxt0601)
RxJava2 源代码解析(一)的更多相关文章
- Spring源代码解析
Spring源代码解析(一):IOC容器:http://www.iteye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的启动:http://www.itey ...
- Arrays.sort源代码解析
Java Arrays.sort源代码解析 Java Arrays中提供了对所有类型的排序.其中主要分为Primitive(8种基本类型)和Object两大类. 基本类型:采用调优的快速排序: 对象类 ...
- Spring源代码解析(收藏)
Spring源代码解析(收藏) Spring源代码解析(一):IOC容器:http://www.iteye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的 ...
- volley源代码解析(七)--终于目的之Response<T>
在上篇文章中,我们终于通过网络,获取到了HttpResponse对象 HttpResponse是android包里面的一个类.然后为了更高的扩展性,我们在BasicNetwork类里面看到.Volle ...
- Cocos2d-x源代码解析(1)——地图模块(3)
接上一章<Cocos2d-x源代码解析(1)--地图模块(2)> 通过前面两章的分析,我们能够知道cocos将tmx的信息结构化到 CCTMXMapInfo.CCTMXTilesetInf ...
- Android EventBus源代码解析 带你深入理解EventBus
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40920453,本文出自:[张鸿洋的博客] 上一篇带大家初步了解了EventBus ...
- 源代码解析Android中View的layout布局过程
Android中的Veiw从内存中到呈如今UI界面上须要依次经历三个阶段:量算 -> 布局 -> 画图,关于View的量算.布局.画图的整体机制可參见博文 < Android中Vie ...
- Android xUtils3源代码解析之网络模块
本文已授权微信公众号<非著名程序猿>原创首发,转载请务必注明出处. xUtils3源代码解析系列 一. Android xUtils3源代码解析之网络模块 二. Android xUtil ...
- Android View体系(八)从源代码解析View的layout和draw流程
相关文章 Android View体系(一)视图坐标系 Android View体系(二)实现View滑动的六种方法 Android View体系(三)属性动画 Android View体系(四)从源 ...
随机推荐
- NYOJ82 迷宫寻宝(一)【BFS】
迷宫寻宝(一) 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描写叙述 一个叫ACM的寻宝者找到了一个藏宝图.它依据藏宝图找到了一个迷宫,这是一个非常特别的迷宫,迷宫里有N个 ...
- SQLite使用事务
关键代码 SQLiteDatabase db = myDataHelper.getWritableDatabase(); // 开启事务 db.beginTransaction(); try{ db. ...
- JavaScript对象浅复制
1.概述 Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target). 注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面 ...
- magento安装wordpress
说起来事实上很easy,如今简诉一下安装过程 1.到magento connect界面安装magento扩展,地址:http://www.magentocommerce.com/magento-con ...
- Word基本文档字体设置
另:段落行距选择:固定值:26/28
- Iterating elements using NightWatchJS
1) used the following strategy to iterate over DOM elements using Nightwatch: // Executing a functio ...
- 通过Cloudera Manager安装CDH 5.6
CDH的简介 大家常常说CDH.其全称是:Cloudera's Distribution Including Apache Hadoop.简单的说是Cloudera公司的Hadoop平台,是在Apac ...
- Redis 的学习和使用
安装Redis 官方网站:http://redis.io/ 官方下载:http://redis.io/download 可以根据需要下载不同版本 windows版:https://github.com ...
- Atitit..jdk java 各版本新特性 1.0 1.1 1.2 1.3 1.4 1.5(5.0) 1.6(6.0) 7.0 8.0 9.0 attilax 大总结
Atitit..jdk java 各版本新特性 1.0 1.1 1.2 1.3 1.4 1.5(5.0) 1.6(6.0) 7.0 8.0 9.0 attilax 大总结 1.1. Java的编年史2 ...
- Shell计算器
#!/bin/bash # filename : jisuan.sh # description : add, subtract, multiply, and divide print_usage() ...