歡迎回來!看來你想更多的瞭解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中發送。
最終,咱們得到搜索結果,並展現給用戶。