從案例學RxAndroid開發(下)

歡迎回來!看來你想更多的瞭解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

相關廠商內容編程

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中發送。

最終,咱們得到搜索結果,並展現給用戶。

相關文章
相關標籤/搜索