转载

从案例学RxAndroid开发(下)

欢迎回来!看来你想更多的了解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的监听代码。

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

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

  1. 调用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中发送。

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

有关RxJava就说这么多了,希望这两篇文章能帮你了解RxJava的基础。强烈建议你自己探索有关RxJava的其他方面。如果你有问题或者只是想说点什么,欢迎在下方留言。

原文  http://www.infoq.com/cn/articles/rxandroid-basics-2
正文到此结束
Loading...