RxJava 中的Map函数原理分析
首先看一段Map函数的使用代码:
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
subscriber.onNext(123);
}
}).map(new Func1<Integer, String>() { @Override
public String call(Integer integer) {
return integer.toString();
}
}).subscribe(new Subscriber<String>() {
public static final String TAG ="Test" ; @Override
public void onCompleted() {
} @Override
public void onError(Throwable e) {
} @Override
public 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);
}
到现在为止,整个流程代码就分析完成了
RxJava 中的Map函数原理分析的更多相关文章
- map函数原理
# -*- coding: utf-8 -*- #python 27 #xiaodeng #map函数 #map函数会对一个序列对象中的每一个元素应用被传入的函数,并返回一个包含了所有函数调用结果的一 ...
- perl编程中的map函数示例
转自:http://www.jbxue.com/article/14854.html 发布:脚本学堂/Perl 编辑:JB01 2013-12-20 10:20:01 [大 中 小] 本文介绍 ...
- Python中的map()函数和reduce()函数的用法
Python中的map()函数和reduce()函数的用法 这篇文章主要介绍了Python中的map()函数和reduce()函数的用法,代码基于Python2.x版本,需要的朋友可以参考下 Py ...
- python中的map()函数
MapReduce的设计灵感来自于函数式编程,这里不打算提MapReduce,就拿python中的map()函数来学习一下. 文档中的介绍在这里: map(function, iterable, .. ...
- Python连载43-current中的map函数、xml文件
一.current中的map函数 1.map(fn,*iterable,timeout=None) (1)跟map函数相类似(2)函数需要异步执行(3)timeout代表超时时间 (4)map和sub ...
- 关于boost中enable_shared_from_this类的原理分析
首先要说明的一个问题是:如何安全地将this指针返回给调用者.一般来说,我们不能直接将this指针返回.想象这样的情况,该函数将this指针返回到外部某个变量保存,然后这个对象自身已经析构了,但外部变 ...
- 实现python中的map函数
假设Python没有提供map()函数,自行编写my_map()函数实现与map()相同的功能.以下代码在Python 2.7.8中实现. 实现代码: def my_map(fun,num): i = ...
- Python 中的map函数,filter函数,reduce函数
自学python,很多地方都需要恶补. 三个函数比较类似,都是应用于序列的内置函数.常见的序列包括list.tuple.str. 1.map函数 map函数会根据提供的函数对指定序 ...
- RxJava 中的map与flatMap
1.map和flatMap都是接受一个函数作为参数(Func1) 2.map函数只有一个参数,参数一般是Func1,Func1的<I,O>I,O模版分别为输入和输出值的类型,实现Func1 ...
随机推荐
- js的同步异步
由于js没有多线程,所以处理多任务的时候,可以用异步回调来解决.js中setTimeout.setInterval.ajax(jq中可以选择同步或异步)均会开启异步.遇到异步模块,会将其推入值任务队列 ...
- python之路 django2
Django请求生命周期 首先:对于所有的web框架来说本质就是一个socket服务端,浏览器是socket客户端 路由系统 在Django的urls中我们可以根据一个URL对应一个函数名来定义路由规 ...
- visual studio开发工具的C#主流控件属性一览表
visual studio开发工具的C#主流控件属性一览表 详细的介绍了各控制属性的详细中文介绍 C#控件及常用设计整理 1.窗体 1.常用属性 (1)Name属性:用来获取或设置窗体的名称,在应用程 ...
- tomcat高并发配置调优
最近部署的tomcat,里面放了一个apk提供给测试人员测试,而有一天压测的时候,他们一致反馈下载不了,结果查看日志才发现如下错误: [html] view plain copy INFO: Maxi ...
- Spark高级数据分析· 3推荐引擎
推荐算法流程 推荐算法 预备 wget http://www.iro.umontreal.ca/~lisa/datasets/profiledata_06-May-2005.tar.gz cd /Us ...
- Android系统init进程启动及init.rc全解析
转:https://blog.csdn.net/zhonglunshun/article/details/78615980 服务启动机制system/core/init/init.c文件main函数中 ...
- yum安装memchache
转载地址:http://www.cnblogs.com/jiunadianshi/articles/2001334.html 标准的CentOS5软件仓库里面是没有memcache相应的包的,所以,我 ...
- PHP+MySQL数据库编程的步骤
第一步:PHP连接MySQL服务器 第二步:选择当前要操作的数据库 第三步:设置请求或返回的数据的字符集 第四步:执行各种SQL语句. PHP连接MySQL服务器 1.mysql_connect() ...
- ViewResolver和ResponseBody笔记
处理HttpResponseBody有两种方式,ViewResolver(视图解析器)和ResponseBody ViewResolver.View多用于jsp,ViewResolver的主要作用是把 ...
- springboot集成shiro 前后端分离 统一处理shiro异常
在前后端分离的情况下,shiro一些权限异常处理会返回401之类的结果,这种结果不好统一管理.我们希望的结果是统一管理,所有情况都受我们控制 就算权限验证失败,我们也希望返回200,并且返回我们定义的 ...