Rxjava2-小白入门(三)

前言

继续上篇的Rxjava2的入门实例,把剩下的运用Rxjava的实例讲下,首先要说名下本文会用到Rxbinding的知识,他相当于Rxjava的辅助工具,在引入他的时候会自动帮我们引入Rxjava,在本文中我就不具体讲解了,用法比较简单,没解除的同学找些相关的文章,相信很快就能上手的,。在这里我把依赖写下

compile 'com.jakewharton.rxbinding2:rxbinding:2.0.0'

这个版本默认引入的是Rxjava2.0.2的版本


Rxjava2的操作符

  • create
  • just
  • fromArray
  • map
  • flatMap
  • zip
  • filter
  • time
  • merge
  • retry
  • retryWhen
  • range
  • Interval
  • ...

Rxjava2的使用场景

  • 登陆后获取用户信息
  • 关键词搜索
  • 防止按钮重复点击
  • 购物车合并本地和网络数据
  • 发送验证码倒计时

关键词搜索

一般情况我们监听EditText控件,当值发生改变去请求搜索接口,如下:

a: 可能导致很多没有意义的请求,耗费用户流量(因为控件的值每更改一次立即就会去请求网络,而且只是最后输入的关键字是有用的)

b:可能导致最终搜索的结果不是用户想要的. 例如,用户一开始输入关键字’AB’ 这个时候出现两个请求, 一个请求是A关键字, 一个请求是AB关键字. 表面上是’A’请求先发出去, ‘AB’请求后发出去. 如果后发出去的’AB’请求先返回, ‘A’请求后返回,那么’A’请求后的结果将会覆盖’AB’请求的结果. 从而导致搜索结果不正确.

在写代码之前我们先介绍下我们要用到的操作符debounce它属于过滤操作符

这是官方文档给出的解释,从解释中我们也不难看出他的用法。那么下面我在实例中去使用吧!

 RxTextView.textChanges(mView)//通过Rxbinding的textChanges()监听AutoCompleteTextView文字的变化,他是一个Obervable对象
                .debounce(200, TimeUnit.MILLISECONDS)//利用debounce操作符延迟发送 TimeUnit.MILLISECONDS(毫秒)指定一个参数的单位
                .subscribeOn(AndroidSchedulers.mainThread())//通过Rxbinding监听控件必须在主线程
                .filter(new Predicate<CharSequence>() {
                    @Override
                    public boolean test(CharSequence charSequence) throws Exception {
                        //过滤为空的数据 避免多余请求
                        return charSequence.toString().trim().length() > 0;
                    }
                })
                .flatMap(new Function<CharSequence, ObservableSource<List<String>>>() {
                    @Override
                    public ObservableSource<List<String>> apply(CharSequence charSequence) throws Exception {
                        Log.d(TAG, "apply: " + charSequence.toString());
                        String request = charSequence.toString().trim();//输入的内容
                        /**
                         * 通过输入的内容request发起网络请求
                         * 返回一个模糊匹配的字符串集合用于显示
                         * 这里我们构建一个假的数据
                         */
                        List<String> mList = new ArrayList<String>();
                        mList.add("abc");
                        mList.add("abd");
                        mList.add("abop");
                        mList.add("ac");
                        return Observable.just(mList);
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<List<String>>() {
                    @Override
                    public void accept(List<String> strings) throws Exception {
                        Log.d(TAG, "accept: " + strings.toString());
                        ArrayAdapter<String> adapter = new ArrayAdapter<String>
                                (getApplicationContext(), android.R.layout.simple_list_item_1, android.R.id.text1, strings);
                        mView.setAdapter(adapter);
                    }
                });
    }

这就是一个简单模拟关键词搜索的实例,但是虽然我们满足了上面提到的要求a,但是要求b也就是可能返回的数据先后不同可能会导致结果不是们想要的,那么该怎么处理呢?通过文档我们找到了这样一个操作符switchMap,让我们来看看他的使用

这个操作符正好符合我们的业务要求,同时他也属于变换操作符,所以我们自需要把flatmap改成switchMap就可以了。这样我们2者的区别和debounce的用法结合实例是不是更加深刻呢?


防止按钮重复(连续)点击

在实际应用中可能在提交信息,登录的时候每次点击按钮就会发送网络请求,当网络比较慢的时候或是其他原因已经请求网路只是返回的数据比较慢,当我们连续点击就会连续的发送请求,这样的结果必然不是我们想要的。

ThrottleFirst: 允许设置一个时间长度,之后它会发送固定时间长度内的第一个事件,而屏蔽其它事件,在间隔达到设置的时间后,可以再发送下一个事件

这个操作符就很好的解决了这个问题

 RxView.clicks(mButton).throttleFirst(2, TimeUnit.SECONDS).subscribe(new Consumer<Object>() {
            @Override
            public void accept(Object o) throws Exception {
                SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String dateStr = dateformat.format(System.currentTimeMillis());
                Log.d(TAG, "accept: "+dateStr);
            }
        });

我在不断点击的情况下,输出结果:

10-08 21:51:07.008 3950-3950/com.example.ggxiaozhi.rxjava D/Main3Activity: accept: 2017-10-08 21:51:07
10-08 21:51:09.168 3950-3950/com.example.ggxiaozhi.rxjava D/Main3Activity: accept: 2017-10-08 21:51:09
10-08 21:51:11.308 3950-3950/com.example.ggxiaozhi.rxjava D/Main3Activity: accept: 2017-10-08 21:51:11
10-08 21:51:13.398 3950-3950/com.example.ggxiaozhi.rxjava D/Main3Activity: accept: 2017-10-08 21:51:13

可以看到2秒内自能点击一次。

注意:此时可以用ThrottleFirst也可以用debounce 效果是一样的 但是 ThrottleFirst发出的是第一个 debounce 发出的是最后一个 都是保证单位时间内只能发送一次 但是原理还是有些不同的,过会2个例子也不难比较区别


购物车合并本地和网络数据

现在有这么一种情况,你在上班的时候偷偷用电脑上淘宝准备买衣服看重了一双鞋子和衣服加入购物车。在回家的路上用手机又加入购物车裤子和衬衫。等你回家的时候准备用手机购买,购物车里应该是所有的商品都在的,那么我们就需要把手机的和web端合并在一起并展示。这时我们就可以用到merge操作符。

在使用前我们先了解下merge:

关于merge的官方文档和图片分析还是比较简单的。不理解的话等我们讲完实例后回头在来看看。下面是具体代码:

  mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View v) {

                /*两者合并*/
                Observable.merge(getObervableLocal(), getObervableWeb()).subscribeOn(Schedulers.io()).
                        observeOn(AndroidSchedulers.mainThread()).
                        subscribe(new Consumer<List<User>>() {
                            @Override
                            public void accept(List<User> users) throws Exception {
                                for (int i = 0; i <users.size() ; i++) {
                                    Log.d(TAG, "accept: "+users.get(i).getName());
                                }
                            }
                        });
            }
        });
    }
    /**
     * 本地数据(从数据库中取)
     *
     * @return 返回本地数据(手机端)的购物车信息
     */
    public Observable<List<User>> getObervableLocal() {
        //用User对象代表商品实例
        //我们用手机购买一般数据会缓存到手机的数据库当中
        User user = new User("裤子", "16元");
        User user1 = new User("衬衫", "18元");

        List<User> mList = new ArrayList<>();
        mList.add(user);
        mList.add(user1);
        return Observable.just(mList);
    }

    /**
     * web数据(从网络中请求)
     *
     * @return 返回网络数据
     */
    public Observable<List<User>> getObervableWeb() {
        //网络请求 查看服务器购物车是否有数据
        User user = new User("衣服", "20元");
        User user1 = new User("裤子", "22元");

        List<User> mList = new ArrayList<>();//模拟请求返回的数据
        mList.add(user);
        mList.add(user1);
        return Observable.fromArray(mList).subscribeOn(Schedulers.io());//网络请求在子线程
    }

运行结果:

10-09 12:39:08.678 11602-11602/com.example.ggxiaozhi.rxjava D/Main3Activity: accept: 裤子
10-09 12:39:08.678 11602-11602/com.example.ggxiaozhi.rxjava D/Main3Activity: accept: 衬衫
10-09 12:39:08.678 11602-11602/com.example.ggxiaozhi.rxjava D/Main3Activity: accept: 衣服
10-09 12:39:08.678 11602-11602/com.example.ggxiaozhi.rxjava D/Main3Activity: accept: 裤子

注意其实合并的操作符还有zip和zipWith,其实2者差不多只是参数不一样。用法也是比较简单zip操作符也可以看看这篇文章。实际操作下会更加深印象。这里我就不咱代码了。


发送验证码倒计时

这个实例我们用到Interval操作符:

具体代码操作:


所有的实例都讲完了我们在看下retryWhen和retry,range操作符。

retry操作符

retryWhen和retry的主要区别概括来说就是retryWhen将错误的信息发送下去(出错了就发送错误信息),retry是出错了会先尝试重新订阅再发送一变,当达到设置的重试次数时还没有成功才会发出错误的信息


总结:感觉文章写的好乱,主要的原因是因为本身也在学习中很多东西总结的不够透彻,虽然看了很多文章但是自己写起来还是会乱乱的,以后会努力希望一次比一次好,作为小白,这是我自身的学习笔记。如果有错误希望大家指出,我将不胜感激。

推荐文章: Rxjava2 RxJava2操作符 RxJava/RxAndroid 使用实例实践 Rxjava2我觉得关于rxjava2这个系列真的非常好很值得学习

代码地址

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小樱的经验随笔

CTF---Web入门第八题 Guess Next Session

Guess Next Session分值:10 来源: iFurySt 难度:易 参与人数:3870人 Get Flag:1672人 答题人数:1690人 ...

3929
来自专栏非著名程序员

Android 插件化突破应用市场无法上广告的问题

先简单的描述一下在广告方面遇到的问题. 开发一款App有了一定的用户量之后通常会想接入第三方广告来实现变现, 然而在很多市场不让这类带广告的App上架,除非接的...

2466
来自专栏水击三千

UML学习-状态图

1.状态图概述 状态图(Statechart Diagram)主要用于描述一个对象在其生存期间的动态行为,表现为一个对象所经历的状态序列,引起状态转移的事件(E...

27510
来自专栏java闲聊

设计模式之适配器模式适配器模式

当我们的手机接口Type-A时,但是数据线只有Type-C的时候,就需要用转接口做适配,这种情况下就要增加一个适配器

1305
来自专栏Phoenix的Android之旅

零基础理解RxJava和响应式编程

RxJava发展到现在已经在2016年推出了第二代。可能你听说过很多人讲起RxJava,但是很少在实际项目开发中用到它。 原因很简单,RxJava虽然很好用,但...

1071
来自专栏晨星先生的自留地

关于一次渗透引发的一个php木马的分析

3935
来自专栏Flutter入门

RecyclerView 源码分析-开编

看了又看,任然对其一知半解。用了又用,发现其真的太美。RecyclerView的设计和书写实在是太惊艳了,日常又使用的相当频繁。虽然之前就看过其他的源码分析,故...

2462
来自专栏一直在跳坑然后爬坑

RxJava2操作符之“Take”

最近我也在学习RxJava2,在网上找了好多文章来读,发现大多数都是说RxJava2和RxJava之间到底有什么区别的,每一个例子都要考虑RxJava里是怎么写...

993
来自专栏项勇

笔记63 | 个人项目“易来”开发记录《一》

1342
来自专栏智能大石头

最终版 Reflector v1.0 (+简单的反流程混淆)

(0415增加简单的反流程混淆功能,满足日常使用需要,不再更新,转向ILSpy,见12点后面) Reflector过期?这可不行!自己动手吧! 看雪上拿到Ref...

2035

扫码关注云+社区

领取腾讯云代金券