深入解析RxJava源码(二)Observable转换原理分析
来源:互联网 发布:centos 包管理器 编辑:程序博客网 时间:2024/05/12 06:54
现在RxJava在Android界已经是无人不知无人不晓的技术了,如果你还不知道RxJava是什么,推荐你去看给 Android 开发者的 RxJava 详解,而本篇博客主要是通过一些例子和源码分析以加深对RxJava的理解,所以看本篇博客时请确保你已对RxJava有了一定的了解。
前一篇博客深入解析RxJava源码(一)Observable对象的构建我们对Observable的构建部分做了深入分析,接下来我们将要对RxJava的核心思想——-“转换”做一些深入的研究,如果你想知道最终的实现为什么是这样的,NotRxJava懒人专用指南,这篇博客可能会给你一些启发。
我们还是从最简单的例子说起吧:
public static void map() { Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { Log.d("demo", "OnSubscribe call"); subscriber.onNext("100"); subscriber.onNext("200"); subscriber.onNext("300"); subscriber.onCompleted(); } }).map(new Func1<String, Integer>() { @Override public Integer call(String s) { Log.d("demo", "Func1 call"); return Integer.parseInt(s); } }).subscribe(new Subscriber<Integer>() { @Override public void onCompleted() { Log.d("demo", "onCompleted"); } @Override public void onError(Throwable e) { Log.d("demo", "onError:" + e.toString()); } @Override public void onNext(Integer i) { Log.d("demo", "onNext:" + i); } }); }
打印结果如下:
OnSubscribe callFunc1 callonNext:100Func1 callonNext:200Func1 callonNext:300onCompleted
这个过程就要相对复杂些了,因为调用subscribe()的对象已经不是create()构造生成的那个Observable对象了,一次map()操作后Observable和OnSubscribe都有两个了,为了便于区分,我们做如下定义:
- create()时产生的两个对象分别为observable1和onSubscribe1;
- map()过程中产生的两个对象分别为observable2和onSubscribe2;
- subscribe()参数subscriber为subscriber1,而OperatorMap的call()返回的为subscriber2。
接下来还是来看看map()的源码吧:
public final <R> Observable<R> map(Func1<? super T, ? extends R> func) { return lift(new OperatorMap<T, R>(func)); }
Func1接口实现了两个对象转换的功能,而Operator则是限定两个Subscriber之间的转换,这里的func就变成了我们map参数中定义的Func1实例,表示将T转化成R。
而map()方法也是直接调用了lift()方法:
public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) { return new Observable<R>(new OnSubscribe<R>() { @Override public void call(Subscriber<? super R> o) { try { Subscriber<? super T> st = operator.call(o); try { st.onStart(); onSubscribe.call(st); } catch (Throwable e) { st.onError(e); } } catch (Throwable e) { o.onError(e); } } }); }
我们来分析下lift()这段代码:
首先我们看到lift()方法里生成了新的Observable和新的OnSubscribe,接下来还是从subscribe()开始分析,当subscribe()被调用后,onSubscribe2的call()方法首先被调用,其中operator.call(o)先被调用,即OperatorMap的call()方法:
@Override public Subscriber<? super T> call(final Subscriber<? super R> o) { return new Subscriber<T>(o) { @Override public void onCompleted() { o.onCompleted(); } @Override public void onError(Throwable e) { o.onError(e); } @Override public void onNext(T t) { try { o.onNext(transformer.call(t)); } catch (Throwable e) { ... } } }; }
新生成的Subscriber赋值给了st,接下来调用 onSubscribe1的call(st),参数为OperatorMap的call()生成的
subscriber2,在自定义的create()里的call()方法的参数实际上就是subscriber2,当调用onXXX回调后,实际上会执行到OperatorMap的call()方法的new Subscriber的回调里,而onNext回调里的代码如下:
o.onNext(transformer.call(t));
transformer是我们map()的参数Func1,前面我们说过,通过这个接口可以实现两个不同对象的转换,这里将subscriber2传递过来的参数转化为subscriber1需要的参数,o为subscriber1,subscriber1为我们subscribe()时的参数。
这里有一点需要强调下:Observable和OnSubscribe是成对存在的,这点对于理解挺重要。
是不是有点晕了,那是因为不同的在T和R之间来回切换,来张图看的更明白!注意这张图里的参数结合前面定义的。
从上面图可以看到,共有两次转换,一次是调用OperatorMap的call()实现从Subscriber-R到Subscriber-T的转换,一次是调用Func1()方法从T到R的转换。
上面我们只是对map()函数的原理做了分析,而flatMap()的原理就要复杂的多,我们先看个例子。
public static List<Person> initPerson() { List<Person> persons = new ArrayList(); Person p1 = new Person(); List<Book> books1 = new ArrayList(); books1.add(new Book("水浒传")); books1.add(new Book("三国演义")); p1.setBooks(books1); p1.setName("张三"); persons.add(p1); Person p2 = new Person(); List<Book> books2 = new ArrayList(); books2.add(new Book("哈利波特")); books2.add(new Book("雷雨")); p2.setBooks(books2); p2.setName("李四"); persons.add(p2); Person p3 = new Person(); List<Book> books3 = new ArrayList(); books3.add(new Book("天下无贼")); books3.add(new Book("英雄本色")); p3.setBooks(books3); p3.setName("王五"); persons.add(p3); return persons; }
接下来我们看转化的代码:
public static void flatMap() { List<Person> persons = initPerson(); Observable.from(persons) .subscribeOn(Schedulers.io()) //将Observable<Person>转化为Observable<Book> .flatMap(new Func1<Person, Observable<Book>>() { @Override public Observable<Book> call(Person person) { Log.d("rxjava", "flatMap === call -- Person"); return Observable.from(person.getBooks()); } }) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<Book>() { @Override public void onCompleted() { Log.d("rxjava", "flatMap === onCompleted"); } @Override public void onError(Throwable e) { Log.d("rxjava", "flatMap ==== onError -- Throwable:" + e.toString()); } @Override public void onNext(Book book) { Log.d("rxjava", "flatMap === onNext -- book:" + book.toString()); } }); }
打印结果如下:
flatMap === call -- PersonflatMap === call -- PersonflatMap === call -- PersonflatMap === onNext -- book:Book{name='水浒传'}flatMap === onNext -- book:Book{name='三国演义'}flatMap === onNext -- book:Book{name='哈利波特'}flatMap === onNext -- book:Book{name='雷雨'}flatMap === onNext -- book:Book{name='天下无贼'}flatMap === onNext -- book:Book{name='英雄本色'}flatMap === onCompleted
我们看到,首先会调用将T转化为Observable-R的Func1的call()方法,接着再回调Subscriber-R的的onNext()方法,最后调用Subscriber-R的onComplete()方法,从而实现了一对多的映射。
从打印结果我们看到,flatMap()是先将这些Book添加到了一个新的集合里,然后再依次发射出去的,并不是每遍历一个Person就发射一次。
- 深入解析RxJava源码(二)Observable转换原理分析
- 深入解析RxJava源码(一)Observable对象的构建
- rxJava的使用--Observable的创建及源码分析(二)
- RxJava 源码解析 —— Observable#defer(...)
- rxJava 源码 原理分析
- rxJava的使用--Observable的创建及源码分析(一)
- rxJava的使用--Observable的创建及源码分析(三)
- RxJava源码分析(二)
- RxJava 1.x Observable分析
- Rxjava解析之二---源码
- RxJava(二:Observable 创建,组合与过滤)
- 理解RxJava(二)操作符流程原理分析
- 深入理解Spark 2.1 Core (二):DAG调度器的原理与源码分析
- 深入理解Spark 2.1 Core (二):DAG调度器的原理与源码分析
- 4、Volley解析(二),源码的深入分析一,缓存线程和网络请求线程
- Rxjava源码(二)-----变换
- 源码阅读--RxJava(二)
- RxJava源码分析(1)
- ZOJ 3601 9th省赛 B Unrequited Love【模拟】
- uva439 Knight Moves
- UVA 1393Highways
- String类的实现
- “社会性动物”的心理
- 深入解析RxJava源码(二)Observable转换原理分析
- 面试】iOS 开发面试题(二)
- XAudio2学习六之播放WAV文件
- leetcode算法刷题
- MFC之MessageBox
- 关于map
- 相对路径和绝对路径
- C#中如何连接SQL数据库 并获取数据
- hdu1159 最长公共子序列