欢迎回来!看来你想更多的了解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\u0026lt;Integer\u0026gt;() {\\ @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的监听代码。
\\\mIncrementButton.setOnClickListener(new View.OnClickListener() {\\ @Override \ public void onClick(View v) { \ mCounter++;\ mCounterEmitter.onNext(mCounter);\ }\});\
\\
可以看到mIncrementButton在onClick()回调方法中做了两件事情:
\\- \\t
让mCounter变量自增。
\\t\\t - \\t
调用mCounterEmitter的onNext()方法并传入mCounter。
\\t\
由于Subject同时也是Observer,所以它也有onNext()方法,因此我们可以通过调用onNext()方法把数据注入管道的输入端,可以理解为同我们在一端中观察自增按钮是否被点击,然后把信息告知管道另一端的Observer。 案例5:Map()
\\我们现在要写一个只显示一个数字的Activity。这将是一个很简单的Activity,因为我们要在这里使用map方法。如果你接触过函数式编程,你可能对map并不陌生。你可以把map当做一个方法,它接收一个数据,然后输出另一个数据,当然输入输出的两个数据之间是有联系的。
\\我们先写一个只发送一个数字4的Single对象。
\\\Single.just(4).map(new Func1\u0026lt;Integer, String\u0026gt;() { \\ @Override \ public String call(Integer integer) { \ return String.valueOf(integer);\ } \}).subscribe(new SingleSubscriber\u0026lt;String\u0026gt;() { \\ @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\u0026lt;String, List\u0026lt;String\u0026gt;\u0026gt;() {\\ @Override \ public List\u0026lt;String\u0026gt; call(String s) { \ return mRestClient.searchForCity(s); \ } \ })\ .observeOn(AndroidSchedulers.mainThread())\ .subscribe(new Observer\u0026lt;List\u0026lt;String\u0026gt;\u0026gt;() { \\ @Override \ public void onCompleted() { }\\ @Override \ public void onError(Throwable e) { } \\ @Override\ public void onNext(List\u0026lt;String\u0026gt; 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中发送。
\\最终,我们获得搜索结果,并展示给用户。 结语
\\有关RxJava就说这么多了,希望这两篇文章能帮你了解RxJava的基础。强烈建议你自己探索有关RxJava的其他方面。如果你有问题或者只是想说点什么,欢迎在下方留言。