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 ...
随机推荐
- 带你走进AJAX(1)
ajax是什么? (1)ajax (asynchronouse javascript and xml) 异步的javascript 和xml (2)ajax是一个粘合剂,将javascript.xml ...
- Storm完整例子
import backtype.storm.spout.SpoutOutputCollector; import backtype.storm.task.TopologyContext; import ...
- 【分库分表】sharding-jdbc—解决的问题
一.遇到的问题 随着互联网技术和业务规模的发展,单个db的表里数据越来越多,sql的优化已经作用不明显或解决不了问题了,这时系统的瓶颈就是单个db了(或单table数据太大).这时候就涉及到分库分表的 ...
- 照着官网来安装openstack pike之创建并启动instance
有了之前组件(keystone.glance.nova.neutron)的安装后,那么就可以在命令行创建并启动instance了 照着官网来安装openstack pike之environment设置 ...
- DDR4中的so-dimm 和component
so-dimm :Small Outline Dual In-line Memory Module (小型双列直插式内存模块) component:直接焊接的ddr4芯片
- Fiddler4工具配置及调试手机和PC端浏览器
Fiddler最大的用处: 模拟请求.修改请求.手机应用调试 Fiddler最新版本 下载地址: http://www.telerik.com/download/fiddler Fiddler 想要监 ...
- [CF730J]Bottles
题目大意:每个瓶子有一定的容积,以及一定的水量,问最少几个瓶子装满所有水,在此基础上还要最小化移动水的体积 第一问用贪心直接求第二问转化成背包问题设dp[i][j]表示前i桶水总容积为j的最多水量,这 ...
- windows,交换机syslog收集
window2008 使用了 windows evtsys_x64 https://download.csdn.net/download/chen_yi_ping/10046676 配置 http ...
- spring boot2.1读取 apollo 配置中心2
第二篇:创建spring boot2.1项目 引用apollo的java客户端jar包 <dependency> <groupId>com.ctrip.framework.ap ...
- 通俗易懂讲解IO模型
前言 说到IO模型,都会牵扯到同步.异步.阻塞.非阻塞这几个词.从词的表面上看,很多人都觉得很容易理解.但是细细一想,却总会发现有点摸不着头脑.自己也曾被这几个词弄的迷迷糊糊的,每次看相关资料弄明白了 ...