转载请标明出处:http://blog.csdn.net/xx326664162/article/details/53611268 文章出自:薛瑄的博客
RxJava最让人兴奋的就是它有各种各样的操作符,什么map呀,flatMap呀各种,我们今天要知其然知其所以然,那么他们是如何实现功能的呢?
下面通过一个例子,逐步深入分析。最后面还会再进行一次总结
例子:
代码块一:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
变换的原理:lift()
这些变换map(),flatMap()虽然功能各有不同,但实质上都是针对事件序列的处理和再发送。而在 RxJava 的内部,它们是基于同一个基础的变换方法: lift(Operator)。
我们先看下进行链式调用map之后,发生了什么。
代码块二:
- 1
- 2
- 3
- 1
- 2
- 3
对,就是调用了lift()!,先来看一下OperatorMap这个类是个什么东西,看似有点多,其实很简单:
代码块三:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
使用传递进来的Func1参数,生成一个Subscriber类型的类,调用OperatorMap的call()函数,将返回这个类
看一下 lift() 的内部实现(仅核心代码):
代码块四:
lift()函数主要就是使用代码块一中,map()函数中的Func1()来生成一个新的Observable,后续的操作使用这个新的Observable。这里知道一下,会有两个Observable对象
- 1
- 2
- 3
- 1
- 2
- 3
来看一下这个新的Observable使用的OnSubscribe
代码块五:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
分析一下这段代码:
- 第 行,
Subscriber<? super T> st = hook.onLift(operator).call(o);
这里的call(),其实就是代码块三中的call()函数,返回的是一个Subscriber的父类 - 第 行,
parent.call(st);
这里的parent是第一个Observable的onSubScribe
先记住这里会有两个Observable,下面会详细分析。
subscribe()源码
Observable.subscribe(Subscriber) 的内部实现是这样的(仅核心代码):
代码块六
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
对整个过程进行详解:
-
Observable.subscribe() 源码(代码块六)第三行的 onSubscribe 指的是 Observable 中的 onSubscribe 对象(在Observable.create()时传入的),但是 lift() 之后的情况就复杂了点。
-
当含有 lift() 时:
- lift() 创建了一个 Observable ,我们把它取名为后Observable$2,加上之前的原始 Observable,同样把它取名为Observable$ 1,已经有两个 Observable 了;
- 同样地,Observable$2 里的新 OnSubscribe$2 加上之前的 Observable$1 中的原始 OnSubscribe$1,也就有了两个 OnSubscribe;
- 当用户调用经过 lift() ,再调用subscribe(), 使用的是Observable$2.subscribe() 。因此 subscribe()源码(代码块六)中的onSubscribe.call(subscriber),也是调用Observable$2 .OnSubscribe$2对象(即在 lift() 中创建Observable时新创建的OnSubscribe(代码块五的这个对象));
-
-
onSubscribe$2.call() 方法中的parent (onSubscribe的父类 ),是Observable$ 1 .onSubscribe$1 。
-
parent.call(st);(代码块五第 行)使用的是Observable$ 1 .onSubscribe$1(任务计划列表),执行新的任务newSubscriber。
-
这样就实现了 lift() 过程,有点像一种代理机制,通过事件拦截和处理实现事件序列的变换。
网上关于这部分的理解,很多博客都使用了这篇博客给 Android 开发者的 RxJava 详解的图,虽然其他部分讲的不错,但是画出的图并不是很贴切代码,理解起来很费劲。所以这类没有引用