深入解析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都有两个了,为了便于区分,我们做如下定义:

  1. create()时产生的两个对象分别为observable1和onSubscribe1;
  2. map()过程中产生的两个对象分别为observable2和onSubscribe2;
  3. 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之间来回切换,来张图看的更明白!注意这张图里的参数结合前面定义的。

RxJava lift()流程图

从上面图可以看到,共有两次转换,一次是调用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就发射一次。

0 0
原创粉丝点击