RxJava实战:变换操作符map的使用姿势及技巧

来源:互联网 发布:mac怎么打出顿号 编辑:程序博客网 时间:2024/04/30 14:21

尊重他人的劳动成果,转载请标明出处:http://blog.csdn.net/gengqiquan/article/details/52757393, 本文出自:【gengqiquan的博客】

关于Map变换操作符,ReactiveX文档上的定义是这样的

对Observable发射的每一项数据应用一个函数,执行变换操作
map

Map操作符对原始Observable发射的每一项数据应用一个你选择的函数,然后返回一个发射这些结果的Observable。

RxJava将这个操作符实现为map函数。这个操作符默认不在任何特定的调度器上执行。

第一次看文档的时候看到一堆这种图,什么玩意儿!然后看多了就懂了。
map变换操作符的作用是把每一个(T类型的)Observable通过一些列代码变换成另外一种(R类型的)Observable
也就是图上的把圆圈变成三角。

Observable就是流,把他当做一种结构,这种结构具有类型, 这种类型可以应用rx操作。然后实际进行RX操作的时候操作的其实是对应的类型的对象。

在Java里的实现为

这里写图片描述

可以看到方法的定义,传入的是一种类型T(super前面的?)Observable,返回的是 另一种类型R以及R的子类(extends前面的?)Observable

比如现在我们有一个 String类型的Observable,现在要把它通过rx操作变换成integer类型的Observable
代码可以这样写

   rx.Observable.just("s")                .map(new Func1<String, Integer>() {                    @Override                    public Integer call(String s) {                        return Integer.valueOf(s);                    }                })

使用lambda精简后可以这样写

rx.Observable.just("s")                .map(s-> {return Integer.valueOf(s);})

甚至可以这样写

   rx.Observable.just("s")                .map(s-> Integer.valueOf(s))

String就是我们上面说的T类型,Integer就是我们上面说的R类型。你可能会觉得把String类型转换成integer而已,这样写是不是太复杂了,别担心,这只是个例子,为了尽量简单的告诉大家map的作用
想象一下,你从服务端获取了一个json数据,但界面最终想要的可能只是里面的某个对象。但你又不得不兼容错误处理,状态码判断,传统的写法可能是写在一个函数里,然后进行各种解析判断比如下面这样

                .Success(json -> {                    BaseModel model = new BaseModel(json );                    if (model.status) {                        mMakeParams = params;                        MakePriceOrderInfo info = (MakePriceOrderInfo) JsonUtil.fromJson(model.data, MakePriceOrderInfo.class);                        startActivity(new Intent(mContext, PayActivity.class)                                .putExtra("type", "2")                                .putExtra("order_id", info.getOrder_id()));                    } else {                        ToastUtil.showShort(mContext, model.msg);                    }                })                .Error(v -> ToastUtil.showShort(mContext, v[1]))

BaseModel 是服务器返回的固定格式

public class BaseModel {    public String data;    public String msg;    public boolean status;}

但你不其实并不想最终的订阅对象(界面赋值函数)去处理太多的条件判断。或者对象类型变换。
因为那样耦合很重,同时代码也并不利于阅读。此时你就可以利于map操作符去对数据源进行变换,变换成订阅对象需要的类型再传递给订阅对象
比如这样

                    .map(s -> new BaseModel(s))                    .subscribeOn(Schedulers.newThread())                    .observeOn(AndroidSchedulers.mainThread())                    .filter(model -> model.trueStatus(context))//筛选操作符,只返回为真的情况下的数据                    .map(model -> model.data);                    .subscribe(data -> {                    String report_id = (String) JsonUtil.parreskey(data, "report_id");                    if (Util.isEmpty(report_id)) {                        showBuyDialog( data);                    } else {                        startActivity(new Intent(this, MakePriceActivity.class)                                .putExtra("isleft", true)                                .putExtra("report_id", report_id));                    }                }, e -> ToastUtil.showShort(mContext, e.getMessage()));

trueStatus方法判断是否返回正确的数据,否则toast提示

    public boolean trueStatus(Context context) {        if (status) {            return true;        } else {            ToastUtil.showShort(context, msg);            return false;        }    }

如此一来你的订阅对象subscribe只需要处理他自己所需要的data 数据了。而不用管在把这个数据给他之前你做了多少事情,因为他不需要在意这些事。

我建了一个QQ群(群号:121606151),用于大家讨论交流Android技术问题,有兴趣的可以加下,大家一起进步。

0 0
原创粉丝点击