欢迎回来!看来你想更多的了解RxJava。若是你尚未看第一部分(此处连接有待修改),推荐先看第一篇。如今咱们来看其余几个例子。再说一遍,全部的例子均可以在这个repo里找到。在每一个例子的开始,我都会说明代码是属于哪一个Activity的。 案例4:Subjects前端
如今咱们写一个Activity,里面要展现一个数字并有一个自增按钮。在看代码以前,先介绍另外一个有关RxJava的概念,Subject。Subject这个对象既是Observable又是Observer,我会把Subject想象成一个管道:从一端把数据注入,结果就会从另外一端输出。java
Subject有好几类,在这里咱们使用最简单的:PublishSubject。使用PublishSubject时,一旦数据从一端注入,结果会当即从另外一端输出。android
首先咱们要写这个管道的输出端。刚才说了Subject也是Observable,也就是说咱们能够像观察任何一个Observable同样观察它。这段代码的功能就是观察管道的输出端到底输出了什么。咱们在这里写一个很简单的Observer来更新mCounterDisplay控件。git
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的监听代码。github
相关厂商内容编程
mIncrementButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCounter++; mCounterEmitter.onNext(mCounter); } });
能够看到mIncrementButton在onClick()回调方法中作了两件事情:性能优化
让mCounter变量自增。服务器
调用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中发送。
最终,咱们得到搜索结果,并展现给用户。