RxJava2 转换操作符之Map()方法

前言:
本文将在Rx官方解释的基础上,再融合其它国内讲解的文章。尽量用最简单的,易懂的方式,解释map()操作符。解释的过程,以问答的形式,先从整体简单解释入手,并配上能跑的示例代码(0 warnings, 0 errors)。先知道能做什么和怎么做,再讲原理,并尽量做到中英融合解释。(建议用PC端阅读,图片可以放大。排版,也有利于阅读)

一、需要了解的知识点:
Observer与Consumer的区别:后者是简化了前者,减去了许多回调接口。注意,重要的事说三遍:他们都是充当观察者角色他们都是充当观察者角色他们都是充当观察者角色。其它详情,可以参考这篇:Observer与Consumer的区别

二、Map的操作流程图解
上面的线,表示原始数据。下面的线,表示转换后的数据。中间的块,代表转换过程。两条线的结尾有一小条竖线,表示结束。箭头的方向,从左到右,表示运行过程,是从左到右跑的。
这里写图片描述

三、学习之前,先来看看,一些常见的问题及解答,基于问题来学习Map操作符。

1、map()操作符能做什么?
答:map()操作符用于转换一组数据。至于怎么转换,由你自己指定。比如,简单的对数据进行加减乘除处理。又比如,将某一个类转成另一个类。又比如,将一组User类对象(userName是User类的一个字段),转成一组userName对象。

2、那它是什么时候开始转换,或者说,是如何触发转换事件的?然后,又是在哪里转换的?最后,它又是如何转换的?
答:问的有点多。。一个一个来。

  • map()是什么时候开始转换的?(即如何触发转换事件),一旦,可(被)观察者(Observable),被观察者(Observer或者Consumer)订阅了,就开始进行转换。那问题来了,怎么订阅?通过设置监听回调,来建立订阅关系。
  • 那在哪里进行转换处理呢?,在这个R apply(@NonNull T t) 方法里进行处理。RT 都是泛型。
  • 那它又是如何实现转换的?,从上一条可以看出,R apply(@NonNull T t) 方法,有两个泛型。传入apply方法的T是原数据类型,由apply方法返回的R类型,即是转换后的类型。具体的转换逻辑,在apply()方法里面,由你自己实现。

3、说了这么多,示例代码呢?要复制粘贴就能跑的那种(0 warnings,0 errors)。
答:好,但你得先配置RxJava2库。同时,在看之前,给你点提示,助你阅读。因为RxJava2是基于观察者模式,以响应流的方式对数据进行异步请求处理。所以,你在阅读代码时,只要遵循简单的从上到下的思考逻辑即可。

      public static void actionMap() {

        List<Integer> list = Arrays.asList(1,2,3);

        Observable.fromIterable(list)
                .map(new Function<Integer, String>() {
                    @Override
                    public String apply(Integer integer) throws Exception {
                        // Converts integer into string.
                        return String.valueOf(integer);
                    }
                }).subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        // prints the converted value
                        log("accept=" + s );
                    }
                });
    }

我们先从上到下来分析这段代码。

首先,Observable(被观察者),通过调用fromIterable来接收一个list,做为数据源(原始数据,被转换的数据)。fromIterable在接收到数据源后,会返回调用它的Observable对象。

接着,Observable会调用map()操作符。注意啦!整容部分要开始啦。 map()操作符,接收一个函数式接口Function< T , R>。这个接口带有两个泛型参数,T是要被整容的数据的类型,R则是被整容后的结果数据的类型。然后,只要订阅关系被建立,map()操作符就会通过调用Function接口里面唯一的方法 R apply(@NonNull T t)。这个方法的作用,就像手术室的作用。T是被整容前的数据。R则是整容后的数据。T–> 整容手术室apply()–> R,就是这样一个过程。那么,这个整容后的数据,交给谁呢?在return R后,R就被Observable给接收了,同时map()方法本身,也会返回一个Observable对象。。。注意,apply()返回的是R,map()返回的才是Observable

最后,要做的就是建立订阅关系。因为map()返回了一个Observable,所以,就可以再通过Observable,来调用一个subscribe方法,建立订阅关系。subscribe方法接收一个接口做为参数(Observer or Consumer)。代码片段中,以一个Consumer为demo。可以看到Consumer接口里面有一个void accept(T t) 方法。这个方法里面有一个T类型,这个T类型,即是被整容后的数据的类型。变量t,则是被整容后的数据。剩下的,你想要对这个被整容后,变漂亮的t做什么下流的事,我就不管了。

上面部分是以Consumer为例,再举一个以Observer为例的,同样地,让我们来看代码:

     Observable.fromIterable(list)
                .map(new Function<Integer, String>() {
                    @Override
                    public String apply(Integer integer) throws Exception {
                        // Converts integer into string.
                        log("apply");
                        return String.valueOf(integer);
                    }
                }).subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        // d.dispose(); Cancel Converts
                        log("onSubscribe" );
                    }

                    @Override
                    public void onNext(String s) {
                        // get 's' from apply().
                        log("onNext=" + s );
                    }

                    @Override
                    public void onError(Throwable e) {
                        // invoked when an exception occurred.
                        // if onError be invoked, The onComplete will never be invoked.
                        // it means the Observer will invoke either the onError or the onComplete.
                        log("onError");
                    }

                    @Override
                    public void onComplete() {
                        // invoked when transforming job done.
                        log("onComplete");
                    }
                });

这是输出的信息:

D/TransformingOperations: onSubscribe 
D/TransformingOperations: apply  
D/TransformingOperations: onNext=1 
D/TransformingOperations: apply 
D/TransformingOperations: onNext=2  
D/TransformingOperations: apply 
D/TransformingOperations: onNext=3  
D/TransformingOperations: onComplete 

前面部分代码,跟Consumer的没区别。重点看Observer回调部分。可以这样理解,apply()方法每执行一次,onNext就会被执行一次。直到所有数据都被转换成功后,onComplete方法就会被调用。如果,在这个转换的过程中,发生什么异常。那么,就不会执行onComplete,而是执行onError方法。然后,onSubscribe最先被调用,所以,可以在这里做一些准备工作。至于线程切换调度的,不属于操作符的讲解范畴,这里就不做示例解释了。


本篇到此结束,如果觉得,问答过程或是分析过程,有什么不易理解,或不到位的。可以在评论区,指出。欢迎批评指正。

附上可以跑的代码(0 warnings, 0 errors):
https://github.com/SuperBeagleDog/OkMVP

注意:
这个库里面有很多东西,RxJava2的转换操作符部分的demo位于:com.lyf.okmvp.demo.rxjava2包下的TransformingOperations类里面。

用法:
1、直接在com.lyf.okmvp.ui包下的MainActivity类里的onCreate()方法里面,直接调用:

TransformingOperations.actionMap(); // 静态方法。

2、也可以复制TransformingOperations类到你的项目里,去为所欲为。但前提时,你得有配置过RxJava和RxAndroid。配置方法,自行百度,或参考我的OkMVP库。


下一篇FlatMap操作符地址:RxJava2 转换操作符之FlatMap()方法

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值