深入解析RxJava源码(二)Observable转换原理分析

现在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 call
Func1 call
onNext:100
Func1 call
onNext:200
Func1 call
onNext:300
onCompleted

这个过程就要相对复杂些了,因为调用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 -- Person
flatMap === call -- Person
flatMap === call -- Person
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 === onNext -- book:Book{name='英雄本色'}
flatMap === onCompleted

我们看到,首先会调用将T转化为Observable-R的Func1的call()方法,接着再回调Subscriber-R的的onNext()方法,最后调用Subscriber-R的onComplete()方法,从而实现了一对多的映射。

从打印结果我们看到,flatMap()是先将这些Book添加到了一个新的集合里,然后再依次发射出去的,并不是每遍历一个Person就发射一次。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值