初涉RxAndroid .map() . filter() flatMap()

Posted 王亟亟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初涉RxAndroid .map() . filter() flatMap()相关的知识,希望对你有一定的参考价值。

转载请注明出处:王亟亟的大牛之路

这周末又败家买了鱼缸和一套设备,本来预备端午出去玩玩的目测只能在家吃土,周五把之前的X项目从X的实现迁移到了RxJava(Rxandroid),这一篇也就写一下相关的知识

强行安利(日更):https://github.com/ddwhan0123/Useful-Open-Source-Android

How to use?

dependencies{
    compile 'io.reactivex:rxjava:1.1.5'
    compile 'io.reactivex:rxandroid:1.2.0'
    }

总共写了两个小例子,先看第一个

看下运行效果:

这里写图片描述

看下日志:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vZ8Zd2IH-1569731388803)(https://img-blog.csdn.net/20160606092216144)]

这个干了什么呢?我们有一个按钮点击之后 随机切换 image,当然图片就都是 异步下载的。

看下代码(先解释大致逻辑和第一部分,方法名命名请无视,哈哈哈)

public class TwoActivity extends AppCompatActivity implements View.OnClickListener {
    private Button testMap;
    private ImageView tiffanyImg;
    private RandomTools randomTools;
    private ArrayList<SampleModel> data;
    private TextView tiffanyText;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_two);

        StatusBarCompat.compat(this, getResources().getColor(R.color.status_bar_color));
        StatusBarCompat.compat(this);

        findId();
        init();
        setListener();
        LogUtils.d("--->Main Thread  id " + Thread.currentThread().getId());
    }

    private void findId() {
        testMap = (Button) findViewById(R.id.testMap);
        tiffanyImg = (ImageView) findViewById(R.id.tiffanyImg);
        tiffanyText = (TextView) findViewById(R.id.tiffanyText);
    }

    private void init() {
        randomTools = RandomTools.getInstance();
        //填充数据
        makeSampleModelData();

    }

    private void setListener() {
        testMap.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.testMap:
                setPhotoForOne(data);
                // setPhotoForTwo(data);
                break;
        }

    }

    private void setPhotoForOne(ArrayList<SampleModel> data) {
        Observable.just(data)
                .subscribeOn(Schedulers.newThread())
                .map(new Func1<ArrayList<SampleModel>, SampleModel>() {
                    @Override
                    public SampleModel call(ArrayList<SampleModel> list) {
                        LogUtils.d("第一个call线程id " + Thread.currentThread().getId());
                        //模拟返回集合的某个元素
                        int randInt = randomTools.getRandom(4);
                        return list.get(randInt);
                    }
                }).map(new Func1<SampleModel, String>() {
            @Override
            public String call(SampleModel sampleModel) {
                LogUtils.d("第二个call线程id " + Thread.currentThread().getId());
                return sampleModel.getContent();
            }
        })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String url) {
                        LogUtils.d("第三个call线程id " + Thread.currentThread().getId());
                        LogUtils.d("--->开始加载 " + url);
                        Glide.with(TwoActivity.this).load(url).into(tiffanyImg);
                    }
                });

    }

    private void setPhotoForTwo(ArrayList<SampleModel> data) {
        Observable.just(data).subscribeOn(Schedulers.newThread())
                .flatMap(new Func1<ArrayList<SampleModel>, Observable<SampleModel>>() {
                    @Override
                    public Observable<SampleModel> call(ArrayList<SampleModel> sampleModels) {
                        return Observable.from(sampleModels);
                    }
                }).filter(new Func1<SampleModel, Boolean>() {
            @Override
            public Boolean call(SampleModel sampleModel) {
                return !sampleModel.getName().equals("");
            }
        }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<SampleModel>() {
            @Override
            public void onCompleted() {
                LogUtils.d("--->onCompleted");
            }

            @Override
            public void onError(Throwable e) {
                LogUtils.e(e);
            }

            @Override
            public void onNext(SampleModel sampleModel) {
                LogUtils.d("--->onNext");
                Glide.with(TwoActivity.this).load(sampleModel.getContent()).into(tiffanyImg);
                tiffanyText.setText(sampleModel.getName());
            }
        });
    }

    //制造数据源
    private void makeSampleModelData() {
        data = new ArrayList<>();
        data.add(new SampleModel("Tiffany one", "http://hiphotos.baidu.com/zhixin/abpic/item/4651a712c8fcc3cea97dbce49045d688d53f206c.jpg"));
        data.add(new SampleModel("Tiffany two", "http://pic.5442.com/2014/0930/06/5442.jpg"));
        data.add(new SampleModel("", "http://img5q.duitang.com/uploads/item/201410/22/20141022214043_5EEKH.thumb.224_0.jpeg"));
        data.add(new SampleModel("Tiffany four", "http://img5.duitang.com/uploads/item/201512/08/20151208163159_HGEM2.thumb.224_0.png"));
        data.add(new SampleModel("Tiffany five", "http://img4.duitang.com/uploads/item/201510/29/20151029224537_ijEKF.thumb.224_0.jpeg"));
    }

}

首先,我们在初始化的时候打了个Thread,然后再接下来的操作力再分别打出Thread,很明显除了加载操作,别的逻辑都让他在子线程里操作,为什么?最后说,先看下去!

这一部分主要实现在于setPhotoForOne这个方法

我们给被观察者传入一个ArrayList<SampleModel>对象,然后让他在新线程里做数据整合的一些行为.subscribeOn(Schedulers.newThread()),接着调用了 .map方法,在这里的Func1我传入了一个键值对。

第一个参数为传入的参数 参数类型也就是ArrayList<SampleModel>

第二个为返回的参数类型 为SampleModel

这极大的简便了我们的操作,不再是传统的传什么返回什么,让我们的代码有更好的拓展性,事件可以分的更清楚(L表达式情况下,传统的回调地狱还是蛮烦的,但是有好有坏,一个可读性好,一个代码少)

并且可以多次调用来满足我们的业务需求,像这样

.map(new Func1<SampleModel, String>() {
            @Override
            public String call(SampleModel sampleModel) {
                LogUtils.d("第二个call线程id " + Thread.currentThread().getId());
                return sampleModel.getContent();
            }
        })

当然我们的UI操作,还是要回到主线程来做,不然会有异常,但是这么做的一个好处是我们的复杂操作(异步,数据库,IO等都利用多CPU的优势来降低主线程的压力) 可以达到尽量避免卡UI的情况,重要的事情说三次 避免卡UI 避免卡UI 避免卡UI

 .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String url) {
                        LogUtils.d("第三个call线程id " + Thread.currentThread().getId());
                        LogUtils.d("--->开始加载 " + url);
                        Glide.with(TwoActivity.this).load(url).into(tiffanyImg);
                    }
                });

然后再来提提另外2个方法 filter() 和 flatMap()

 .flatMap(new Func1<ArrayList<SampleModel>, Observable<SampleModel>>() {
                    @Override
                    public Observable<SampleModel> call(ArrayList<SampleModel> sampleModels) {
                        return Observable.from(sampleModels);
                    }
                })

这里的Func1也是传入2个参数

第一个为传入的类型,第二个是返回的Observable对象

和map一样他们都可以改变类型,但是只是返回的类型不同而已,大家可以根据自己的需求来选择不同的方法。

那返回的Observable又能干吗呢?

我们可以对他进行再次的嵌套,诸如二次just,二次from等等,有很大的拓展性

接下来再来提一下 .filter()

他可以为我们做“筛选”操作,

.filter(new Func1<SampleModel, Boolean>() { @Override public Boolean call(SampleModel sampleModel) { return !sampleModel.getName().equals(""); } })
false就会被过滤掉,也就是不会被观察者所执行

看下Log就清楚了

这里写图片描述

我们name为""的那条数据就没有走onNext方法。

Ok,为什么用RxJava

1 不用再去麻烦的扣Handler做逻辑判断

2 更好的线程处理,方便好用

3 强大的API

源码地址:https://github.com/ddwhan0123/RxAndroidDemo

友情链接:http://gank.io/post/560e15be2dca930e00da1083#toc_1

以上是关于初涉RxAndroid .map() . filter() flatMap()的主要内容,如果未能解决你的问题,请参考以下文章

RxJava 和 RxAndroid 五(线程调度)

RxJava 和 RxAndroid 四(RxBinding的使用)

RxJava 和 RxAndroid 二

RxAndroid + Retrofit callTimeout 不会触发 onError

RxJava 和 RxAndroid 三(生命周期控制和内存优化)

RxAndroid 实践快速入门