• RxJava Map操作详解


    2016-06-06

      RxJava是最近两年火起来的一个框架,核心是异步,但是对于我来说印象最深的是响应式编程的思想。最近刚好想把自己的项目改成用RxJava实现,所以就研究了下。抛物线和大头鬼两位大牛也讲解的很详细和形象,其实RxJava里除了这种响应式的编程思想不太好理解外,操作符也是比较难理解的一部分。响应式编程思想不是三言两语就能讲清楚,想学习的人也不是通过看几遍blog就能学会的。我这里主要是讲操符,通过分解的方式一步一步带领大家看着到底是怎么回事,就以常用的map为例。

    首先看一段伪代码: 

    Observable.create(new Observable.Onsubscrible(){  //------------ Observable one
      @override
      public object call(…subscriber){  //----------------------call one
         ……
         subscriber.onNext();  //-------------- onNext one
         …….
    }
    }).map(new Func1(){ // ----------------------map 操作后返回的为Observable two
      @override
      Public object call(…){   //-----------------------------call two
         ……. 
    }
    
    }).subscrible(new Subscriber(){
       @override
       public void onCompleted(){}
       @override
       Public void onError(){}
     
       @override
       Public void onNext(){  //-------------------------onNext two
         …….
        }
    });

    我将剖析上面的一段RxJava代码。为了一步一步的把问题描述清楚,我们先把上面的代码简化如下,定义observableTemp变量:

    observableTemp.subscrible(new Subscriber (){…..});

     其中ObservableTemp为:

    observableTemp = 
    observable.create(new Observable.Onsubscrible(){  //------------ Observable one
      @override
      public object call(…subscriber){  //----------------------call one
         ……
         subscriber.onNext();  //-------------- onNext one
         …….
    }
    }).map(new Func1(){ // ----------------------map 操作后返回的为Observable two
      @override
      Public object call(…){   //-----------------------------call two
         ……. 
    }
    
    });

       

    第一步,我们先解析subscrible到底做了什么

      hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);

    这是整个subscrible方法的核心。onSubscribeStart返回的是observable.onSubscribe,而observable.onSubscribe是传入参数,为this对象。所以可以把subcrible方法的主要功能简化为:

     ObservableTemp. onSubscribe.call(new Subscriber (){….});

    举例说明下:如果

    ObservableTemp =

    Observable.create(new Observable.Onsubscrible(){

      @override

      public object call(…subscriber){  //---------------1-1

         subscriber.onNext();

    }

    })

    那么ObservableTemp. onSubscribe.call(new Subscriber (){….});分解如下:

    ObservableTemp. onSubscrib = Observable.Onsubscrible()

    这里的1-1传入值按照我们刚才简化后形式,应该是new Subscriber ()。那么整个就成了:

    new Observable.Onsubscrible(){

      @override

      public object call(…subscriber){ 

    ……

         subscriber.onNext();

         …….. 

    }

    }.call(new Subscriber (){….});

    这里的call就是调用的@override的call方法,所以这里进一步分解:

    public object call(){ 

    ……

         new Subscriber (){….}.onNext();

         …….. 

    }

    看明白了吗?其实整个一大段代码只是执行了Subscriber里的onNext方法。

    相信看到这里已经明白了subscribe方法的作用了。但是如果把ObservableTemp展开呢?也就是还原到开头的那段代码,又干了什么事情呢?请看第二步的分解

      

    第二步,map到底做了什么

      我们已经知道ObservableTemp. onSubscribe.call(new Subscriber (){….});其实是通过ObservableTemp里的Onsubscrible.call方法直接调用Subscriber的onNext方法。那么加入map后,到底是怎么一种调用关系呢?Map字面的意思应该是个映射操作,那到底是不是字面上的映射?如果是映射,到底谁和谁之间的映射呢?

     为了方便说明,我们还是把开头第一段代码做个简化,简化为:

    ObservableTemp.map(new Func1(){…}).subcrible(new Subscriber(){…});

    其中ObservableTemp 就是一个简单的对象创建和赋值过程了:

    Observable.create(new Observable.Onsubscrible(){ 
      @override
      public object call(…subscriber){ 
         ……
         subscriber.onNext();
         …….
    }
    }); // 没有什么理解上的难度

    map的操作代码是:

    lift(new OperatorMap<T, R>(func));

    lift是RxJava里核心,几乎大部分Observable操作都是需要用到lift方法。A.lift(Operator op)返回的是一个新的Observable,新Observable中的OnSubscribe为OnSubscribeLift。

    ObservableTemp.map(new Func1(){…}).subcrible(new Subscriber(){…});

    就变成了:

    new Observable(new OnSubscribeLift(){
    @override
      Public object call(…){  
         ……. 
    }
    }).subcrible(new Subscriber(){…}); // ------------------------- 2-2

    是不是很眼熟,Yes, 就是第一步里简化的步骤。那么这里关键的部分来了,OnSubscribeLift里的call做了什么,如果我们把这个搞清楚了,那么map就自然而然的就清楚了。

    OnSubscribeLift里的call主要有两行代码:

    Subscriber<? super T> st = hook.onLift(operator).call(o);
    parent.call(st);

    这里的operator,o ,parent以及 st到底是什么呢?

     因为这里的o是OnSubscribeLift里call方法传入的参数,由2-2可以知道,o其实代表的是new Subscriber()。

    再看operator,由代码可以看出:

    public final <R> Observable<R> map(Func1<? super T, ? extends R> func) {
            return lift(new OperatorMap<T, R>(func));
        }

    这里的operator就是指经过OperatorMap包装过的Operator对象:new OperatorMap<T, R>(new Func1());而hook.onLift(operator)返回的就是operator,那么上面两句代码可以看成:

    Subscriber<? super T> st = (new OperatorMap<T, R>(new Func1())).call(o);
    parent.call(st);

    OperatorMap里的call做了三件事情:

    MapSubscriber<T, R> parent = new MapSubscriber<T, R>(o, transformer); 
    o.add(parent);
    return parent;

    把 new subscriber()和new Func1()(就是transformer对象)通过MapSubscriber封装起来。然后新的Subcriber(MapSubscriber对象)放入订阅列表中,以便最后一起把订阅对象释放。同时返回新的Subcriber。

    根据上述的,

    Subscriber<? super T> st = (new OperatorMap<T, R>(new Func1())).call(o);
    parent.call(st);

    可以看成:

    Subscriber<? super T> st  = new MapSubscriber<T, R>(o, transformer);
    parent.call(st);

    而parent是传入的参数,指ObservableTemp.onSubscribe,也就是开头代码中的Observable one。

    进一步上述两行代码可以看成:

    Subscriber<? super T> st  = new MapSubscriber<T, R>(o, transformer);
    (new Observable.Onsubscrible(){  //------------ Observable one
      @override
      public object call(…subscriber){  //----------------------call one
         ……
         subscriber.onNext();  //-------------- onNext one
         …….
    }
    }).call(st);

    这里的override里的call参数为new MapSubscriber<T, R>(o, transformer); new MapSubscriber<T, R>(o, transformer).onNext主要代码为:

    @Override
     public void onNext(T t) {
        result = mapper.call(t);
        actual.onNext(result);
     }

    Mapper就是transformer对象,也就是new Func1(),而actual就是new subscriber()。也就是说:把Observable one里的类型经过new Func1().call的方法转换成另外一个Subscriber,最后调用new Subscriber的onNext方法。

    所以map整个过程就清楚了:
    A.map(B).subscribe(C) 就是:

    先通过map方法,把A中想要转换的数据通过调用B里的call方法进行转换,最后把转换过的数据用C里的onNext方法进行处理。

    我们抛开onCompleted和onError方法,

    A.map(B).subscribe(C)  <==>  C.onNext (B.call(A.onNext()))

  • 相关阅读:
    performance benchmark : memcached vs Kyoto Tycoon
    Adhesive框架系列文章应用程序信息中心模块实现
    神奇的Redis
    使用代码测试ASP.NET MVC2执行流程
    linq2sql代码大全
    7/17博客园活动浅谈网站架构中缓存的应用所有资料
    浅谈.NET下的多线程和并行计算(十四)并行计算前言
    公司.NET 3.5培训资料分享
    mongodb分片集群(sharding with replica set)配置
    mongodb有关的研究
  • 原文地址:https://www.cnblogs.com/StephenWu/p/5565153.html
Copyright © 2020-2023  润新知