RxJava 中的Map函数原理分析
首先看一段Map函数的使用代码:
Observable.create(new Observable.OnSubscribe<Integer>() {@Overridepublic void call(Subscriber<? super Integer> subscriber) {subscriber.onNext(123);}}).map(new Func1<Integer, String>() {@Overridepublic String call(Integer integer) {return integer.toString();}}).subscribe(new Subscriber<String>() {public static final String TAG ="Test" ;@Overridepublic void onCompleted() {}@Overridepublic void onError(Throwable e) {}@Overridepublic void onNext(String s) {Log.d(TAG, "onNext: "+s);}});
Observable<Integer>Observable1=Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) { subscriber.onNext(123); }
});
create函数构建了一个新的Observable 在Observable的构造函数中将Observable.onSubscribe属性赋值为 Observable.OnSubscribe<Integer>;
Observable<String> Observable2= Observable1.map(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
return null;
}});
通过 map函数构建了一个新的Observable
map函数源码:
public final <R> Observable<R> map(Func1<? super T, ? extends R> func) {
return lift(new OperatorMap<T, R>(func));
}
在map源码中首先通过func(这里的func指的就是Func1<Integer, String>())参数构建一个OperatorMap类;
public OperatorMap(Func1<? super T, ? extends R> transformer) {
this.transformer = transformer;
}
OperatorMap.transformer 也指向了Func1<Integer, String>();
lift函数里面创建了一个新的Observable,而上边的Observable<String> Observable2也就是lift函数创建的;
public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {
return new Observable<R>(new OnSubscribeLift<T, R>(onSubscribe, operator));
}
public final class OnSubscribeLift<T, R> implements OnSubscribe<R>
在构造函数中传了一个OnSubscribeLift对象,因此Observable2.onSubscribe 也就指向了OnSubscribeLift;
public OnSubscribeLift(OnSubscribe<T> parent, Operator<? extends R, ? super T> operator) {
this.parent = parent;
this.operator = operator;
}
在OnSubscribeLift的构造函数中parent 被指向为Observable1中的OnSubscribe(Observable.OnSubscribe<Integer>())
operator指向OperatorMap;
通过Map函数就创建了一个新的Observable,所有开头的例子的代码就变成了
Observable2 .subscribe(new Subscriber<String>() {
public static final String TAG ="125" ;
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
Log.d(TAG, "onNext: "+s);
}
});
然后在分析下subscribe函数:
public final Subscription subscribe(Subscriber<? super T> subscriber) {
return Observable.subscribe(subscriber, this);
}
在Observable.subscribe(subscriber, this); 中的this 指向的是Observable2;
static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
.................
subscriber.onStart();
hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);
return hook.onSubscribeReturn(subscriber);
.................
}
从subscribe函数代码可以看出,最终调用的是onSubscribe的call函数;
此时的onSubscribe指向的是Observable2.onSubscribe 也就是早lift函数中创建的OnSubscribeLift;
在OnSubscribeLift.java 代码中:
public void call(Subscriber<? super R> o) {
.............
Subscriber<? super T> st = hook.onLift(operator).call(o);
st.onStart();
parent.call(st);
............
}
在call函数中参数 Subscriber<? super R> o指向的是subscribe函数中的Subscriber<String>();
call函数的内部首先创建了一个新的 Subscriber<? super T> st;
此时的operator指向的是OperatorMap类
新的Subcriber(MapSubscriber对象)放入订阅列表中,以便最后一起把订阅对象释放。同时返回新的Subcriber。
public Subscriber<? super T> call(final Subscriber<? super R> o) {
MapSubscriber<T, R> parent = new MapSubscriber<T, R>(o, transformer);
o.add(parent);
return parent;
}
static final class MapSubscriber<T, R> extends Subscriber<T> {
public MapSubscriber(Subscriber<? super R> actual, Func1<? super T, ? extends R> mapper) {
this.actual = actual;
this.mapper = mapper;
}
}
在OperatorMap类的call方法中创建了一个新的MapSubscriber对象;
在创建的MapSubscriber对象的构造函数中对字段进行赋值
actual 指向 o 也就是subscribe函数中的Subscriber<String>();
mapper 指向OperatorMap.transformer (指向了map函数的中参数Func1<Integer, String>())
回到在OnSubscribeLift.call 代码中,当创建好新的Subscriber对象后,将执行
parent.call(st);
此时的parent 指向的是Observable1中的OnSubscribe,因此调用的call方法相当于是
public void call(Subscriber<? super Integer> subscriber) {
subscriber.onNext(123);
}
此时的subscriber 就是新建的st(MapSubscriber) 跳转到onNext函数中;
static final class MapSubscriber<T, R> extends Subscriber<T> {
public void onNext(T t) {
R result;
try {
result = mapper.call(t);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
unsubscribe();
onError(OnErrorThrowable.addValueAsLastCause(ex, t));
return;
}
actual.onNext(result);
}
}
此时的参数t为123;执行mapper.call(t);
mapper此时执行的是
public String call(Integer integer) {
return integer.toString();
}
result 就变为了"123";
然后在执行actual.onNext("123");
actual此时就是:
public void onNext(String s) {
Log.d(TAG, "onNext: "+s);
}
到现在为止,整个流程代码就分析完成了
转载于:https://www.cnblogs.com/h20064528/p/6543071.html
RxJava 中的Map函数原理分析相关推荐
- 科学使用python中的Map函数和Filter函数
欢迎关注 "小白玩转Python",发现更多 "有趣" map函数 假设我们想要用现有列表创建一个新的列表,也就是说要在现有列表的基础上,对列表的每个元素进行某 ...
- JDK 中的 BIO 实现原理分析(二十)
今天对JDK 中的 BIO 实现原理进行分析 一.简介 对比 Linux 上网络编程,我们会发现 JDK Socket 的编程逻辑是一模一样的.实际上也是这样,JDK 网络编程也没有做很多事,主要还是 ...
- R语言dplyr包使用recode函数进行数据列内容编码、转换实战:类似于pandas中的map函数(例如,将内容从字符串映射到数值)
R语言dplyr包使用recode函数进行数据列内容编码.转换实战:类似于pandas中的map函数(例如,将内容从字符串映射到数值) 目录
- Python中的map()函数和reduce()函数的用法
Python中的map()函数和reduce()函数的用法 这篇文章主要介绍了Python中的map()函数和reduce()函数的用法,代码基于Python2.x版本,需要的朋友可以参考下
- python用map提取一个数的个十百位数_如何使用python中的map函数?
我们在使用python过程中,为了避免错误删除,会选择做好一个序列后可以插入另外的序列中做为新序列的一部分内容.方便完成一些复杂的工程或多个片段分别编辑后再串成一个完整工程的操作.之前小编向大家介绍了 ...
- python3中调用map函数报错map object at 0x000001EF004D97B8
python3中调用map函数报错<map object at 0x000001EF004D97B8> 在python中这样的一段代码报错: a=map(int,input().split ...
- c++ map 获取key列表_好未来Golang源码系列一:Map实现原理分析
分享老师:学而思网校 郭雨田 一.map的结构与设计原理 golang中map是一个kv对集合.底层使用hash table,用链表来解决冲突 ,出现冲突时,不是每一个key都申请一个结构通过链表串起 ...
- Python高阶函数原理分析及其应用
三 高阶函数, 闭包和装饰器 所谓高阶函数就是把函数做为参数传入的一类函数. 另外, 返回函数的函数也属于高阶函数. 3.1 函数做为参数传入另外一个函数 3.1.1 高阶函数引入 Python中函数 ...
- python中map函数字典映射_浅析python中的map函数
1.map()函数的简介以及语法: map是python内置函数,会根据提供的函数对指定的序列做映射. map()函数的格式是:map(function,iterable,...) 第一个参数接受一个 ...
最新文章
- c++ using 前置声明_C++ 类的前置声明
- 面对“超人革命”,我们是否已做好准备?
- 初探设计:Java继承何时用?怎么用?
- 城管威逼交警“让老百姓笑话”
- linux中.开头的变量,linux中的变量
- CommonJs、AMD 、CMD 前端开发模块化组合
- 鸿蒙os2.0官网公测报名,鸿蒙OS2.0公测版测试资格报名-鸿蒙OS2.0公测版测试资格报名官网地址预约 -友情手机站...
- 如何在命令行更改IP地址
- chrome访问不了go语言中文网
- VMware安装win7操作系统
- 通用-描述文件找不到
- 投票系统C语言程序,C语言课程投票程序系统.doc
- python定义一个整数变量_Python变量和数据类型详解
- 172Echarts - 象形柱图(Dotted bar)
- MySQL报错1406_mysql报错:1406, Data too long for column
- Boost(一)——Boost简介
- 虚拟内存,物理内存,页面文件,还有任务管理器
- Mel spectrum梅尔频谱与MFCCs
- kettle插件加载流程
- iOS WebView白屏问题解决方案
热门文章
- canva画图 图片居中裁剪_Canvas裁剪图片(截选框可拖拽)
- php ip to int_ip地址和int相互转换
- seo从入门到精通_SEO入门到精通(七):SEO工作的流程是什么?
- 【项目实战课】微信小程序图像识别模型前后端部署实战
- 【赠书】图神经网络基础与前沿最新书籍,赠5本学习
- 【GAN优化】从动力学视角看GAN是一种什么感觉?
- 2022版全球及中国消防设备市场营销策略分析与竞争趋势展望报告
- 全球及中国低温纳米定位器行业发展趋势分析与风险评估报告2021-2027年版
- yum源 php7.2,云服务器:CentOS7 yum安装PHP7.2的操作方法
- 03018_监听器Listener