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这个系列真的非常好很值得学习

代码地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,054评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • 前言 上篇文章我们主要讲解了观察者模式。那么这节课我们主要讲解Rxjava2的基本使用和操作符。其实网上的关于Rx...
    g小志阅读 546评论 0 2
  • RxJava2 实战系列文章 RxJava2 实战知识梳理(1) - 后台执行耗时操作,实时通知 UI 更新RxJ...
    泽毛阅读 8,891评论 23 44
  • 古人把每个季节分为三个段,孟、仲、季,秋季的三个月是七、八、九月,对应的是孟秋、仲秋、季秋,农历的八月十五正好是仲...
    薛善强阅读 478评论 0 1