文档章节

从案例学RxAndroid开发(下)

KingBoxing123
 KingBoxing123
发布于 2017/03/11 12:01
字数 1610
阅读 17
收藏 1

欢迎回来!看来你想更多的了解RxJava。如果你还没有看第一部分(此处链接有待修改),推荐先看第一篇。现在我们来看其他几个例子。再说一遍,所有的例子都可以在这个repo里找到。在每个例子的开始,我都会说明代码是属于哪个Activity的。 案例4:Subjects

现在我们写一个Activity,里面要展示一个数字并有一个自增按钮。在看代码之前,先介绍另一个有关RxJava的概念,Subject。Subject这个对象既是Observable又是Observer,我会把Subject想象成一个管道:从一端把数据注入,结果就会从另一端输出。

Subject有好几类,在这里我们使用最简单的:PublishSubject。使用PublishSubject时,一旦数据从一端注入,结果会立即从另一端输出。

首先我们要写这个管道的输出端。刚才说了Subject也是Observable,也就是说我们可以像观察任何一个Observable一样观察它。这段代码的功能就是观察管道的输出端到底输出了什么。我们在这里写一个很简单的Observer来更新mCounterDisplay控件。

mCounterEmitter = PublishSubject.create(); 
mCounterEmitter.subscribe(new Observer<Integer>() {

    @Override
    public void onCompleted() { } 

    @Override
    public void onError(Throwable e) { } 

    @Override
    public void onNext(Integer integer) { 
        mCounterDisplay.setText(String.valueOf(integer));
    } 
});

与第一部分中的例子不同,在这个例子中onNext()会被调用多次。每次发送新的数据时,mCounterDisplay都会展示新的数据。但是PublishSubject怎么发送数据呢?让我们看一下mIncrementButton的监听代码。

相关厂商内容

Native动态化最新技术解析

不可错过的智能时代的大前端

性能优化最佳实践经验谈

Programmers,请开始你的表演

架构师应该把握这些技术趋势

mIncrementButton.setOnClickListener(new View.OnClickListener() {

    @Override 
    public void onClick(View v) { 
        mCounter++;
        mCounterEmitter.onNext(mCounter);
    }
});

可以看到mIncrementButton在onClick()回调方法中做了两件事情:

  1. 让mCounter变量自增。

  2. 调用mCounterEmitter的onNext()方法并传入mCounter。

由于Subject同时也是Observer,所以它也有onNext()方法,因此我们可以通过调用onNext()方法把数据注入管道的输入端,可以理解为同我们在一端中观察自增按钮是否被点击,然后把信息告知管道另一端的Observer。 案例5:Map()

我们现在要写一个只显示一个数字的Activity。这将是一个很简单的Activity,因为我们要在这里使用map方法。如果你接触过函数式编程,你可能对map并不陌生。你可以把map当做一个方法,它接收一个数据,然后输出另一个数据,当然输入输出的两个数据之间是有联系的。

我们先写一个只发送一个数字4的Single对象。

Single.just(4).map(new Func1<Integer, String>() { 

    @Override 
    public String call(Integer integer) { 
        return String.valueOf(integer);
    } 
}).subscribe(new SingleSubscriber<String>() { 

    @Override 
    public void onSuccess(String value) { 
        mValueDisplay.setText(value); 
    } 

    @Override 
    public void onError(Throwable error) { } 
}); 

我们最终要显示Single所发送的数据,但首先我们需要将这个数据从Integer转为String,而这里的解决方法就是使用map()函数。正如刚才所说,map接收一个数据,进行处理而后输出它,这正是我们需要的。现在Single会发送数字4,我们使用map()方法将其转为String,而后交给Observer去展示它。

这个例子中对于map方法的使用很轻量,不过map可是非常强大的,在下一个例子中你可以看到,map可以被用来执行任意代码,在处理数据方面起到很重要的作用。 案例6:综合使用

现在我们要写一个用来根据名字搜索城市的Activity。在这个Activity中,我们要使用在这两篇文章中所学的所有知识并写一个比较大的例子。同时还要介绍一个新的概念:deboundce。开始。

现在我们要写一个PublishSubject,并能接收用书输入进输入框的数据,而后根据输入获取符合的列表,并展示。

mTextWatchSubscription = mSearchResultsSubject
    .debounce(400, TimeUnit.MILLISECONDS)
    .observeOn(Schedulers.io())
    .map(new Func1<String, List<String>>() {

        @Override 
        public List<String> call(String s) { 
            return mRestClient.searchForCity(s); 
        } 
    })
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Observer<List<String>>() { 

        @Override 
        public void onCompleted() { }

        @Override 
        public void onError(Throwable e) { } 

        @Override
        public void onNext(List<String> cities) {
            handleSearchResults(cities); 
        }
    });

mSearchInput.addTextChangedListener(new TextWatcher() {

    @Override 
    public void beforeTextChanged(CharSequence s, int start, int count, int after) { }

    @Override 
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        mSearchResultsSubject.onNext(s.toString()); 
    }

    @Override 
    public void afterTextChanged(Editable s) { } 
});

这段代码有不少内容,让我们一点一点分析。

首先你会看到debounce()方法。这是啥?有啥用?如果你看一下我们是如何给输入框添加监听器的,你会发现每当输入的内容改变时都会有输入发送到mSearchResultsSubject,不过我们不想让用户每点一个键都向服务器请求一次。我们想等一会,等用户停止输入(代表差不多输完)的时候再请求服务器。

而debounce()方法就是做这个的。这个方法告诉mSearchResultsSubject在没有数据传入达400毫秒时才发送数据。意思就是,仅当用户400ms都没有改变输入内容时,Subject才会发送最新的搜索字符串。这样以来我们就不会进行无意义的网络请求了,UI也不会每输入一个字符都更新。

我们想通过RestClient来访问服务器,而因为RestClient涉及IO操作,我们需要在IO Scheduler中进行这个操作,所以要写observeOn(Schedulers.io())。

好了,现在我们会把搜索字段发送到IO Scheduler中,在这里map就要发挥作用了,我们在map方法中通过关键字获取搜索结果的列表。在map中我们可以调用任意外部方法,在这里使用RestClient获取搜索结果。

因为map方法会在IO Scheduler中运行,而我们又要用其返回值填充View,所以要重新切换到UI线程,所以要写observeOn(AndroidSchedulers.mainThread())。现在搜索结果会被发送到UI线程。要注意两个observeOn()方法的顺序,这一点至关重要。现在我们总结一下数据发送的顺序。

mSearchResultsSubject 
            |
            |
            V
        debounce
          ||| 
          |||
           V 
          map 
           | 
           | 
           V
        observer

一个竖杠代表数据在UI线程中发送,三个竖杠代表数据在IO Scheduler中发送。

最终,我们获得搜索结果,并展示给用户。

本文转载自:

共有 人打赏支持
KingBoxing123
粉丝 5
博文 95
码字总数 48684
作品 0
成都
私信 提问
RxJava与RxAndroid的学习之路

RxJava 和 RxAndroid 四(RxBinding的使用) 对Rxjava不熟悉的同学可以先看我之前写的几篇文章 RxJava 和 RxAndroid 一 (基础) RxJava 和 RxAndroid 二(操作符的使用) RxJava 和 RxAndroi...

guozhendan
2018/06/26
0
0
RxAndroid之初体验——Create、From、interval、just、range操作符的基本使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m366917/article/details/52801459 RxAndroid之初体验——Create、From、interval、just、range操作符的基本使...

Aduroidpc
2016/10/12
0
0
RxAndroid的简单应用——实现网络图片的下载

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m366917/article/details/52802933 RxAndroid的简单应用——实现网络图片的下载 版权声明:转载必须注明本文转...

Aduroidpc
2016/10/13
0
0
使用聚合数据的接口进行的RxAndroid学习

Demo数据源是聚合数据的免费Api,地址:https://www.juhe.cn/ 配合Retrofit 完成数据请求 例子比较简单,没事使用什么复杂的操作符。 就是简单的网络数据获取。 一些常用的操作符大家可以参考...

白jian
2016/10/09
144
0
日新月异的Android新技术

学习Android技术开发已经很久啦,感觉Android技术开发太快,几乎每年都有很多新东西出现,想要覆盖所有新东西感觉也不太可能,我这里主要说一下主要的 Android 的主要新技术发展,其实了解 ...

crossmix
2015/11/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Mysql(Mariadb)数据库主从复制

Mysql主从复制的实现原理图大致如下: MySQL之间数据复制的基础是以二进制日志文件(binary log file)来实现的,一台MySQL数据库一旦启用二进制日志后,其作为master,它数据库中所有操作都...

linux-tao
今天
2
0
Mysql(Mariadb)数据库主从复制

Mysql主从复制的实现原理图大致如下: MySQL之间数据复制的基础是以二进制日志文件(binary log file)来实现的,一台MySQL数据库一旦启用二进制日志后,其作为master,它数据库中所有操作都...

Linux就该这么学
今天
2
0
Mysql(Mariadb)数据库主从复制

Mysql主从复制的实现原理图大致如下: MySQL之间数据复制的基础是以二进制日志文件(binary log file)来实现的,一台MySQL数据库一旦启用二进制日志后,其作为master,它数据库中所有操作都...

xiangyunyan
今天
2
0
Android 自定义Path贝塞尔曲线View实践——旋转的花朵

一、关于贝塞尔曲线 在工业设计方面贝塞尔曲线有很多用途,同样,在Android中,贝塞尔曲线结合Path类可以实现更复杂的图形,这里我们给一个案例,来实现一种旋转的花朵。对于贝赛尔曲线的理解...

IamOkay
今天
3
0
7、redis主从复制和sentinel配置高可用

一:redis主从配置 1、环境准备 master : 192.168.50.10 6179 slave1: 192.168.50.10 6279 slave2: 192.168.50.10 6379 2、redis.conf配置文件配置 master port 6179......

刘付kin
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部