天天看點

(完結)Android MVP+Retrofit+dagger2+RxAndroid架構整合(8)----RxAndroid/RxJava篇

作者:hwj3747

轉載請注明

目錄

  • (1)配置篇
  • (2)Lambda表達式
  • (3)icepick篇
  • (4)butterknife篇
  • (5)MVP篇
  • (6)Retrofit篇
  • (7)Dagger2篇
  • (8)RxAndroid/RxJava篇

RxJava介紹

首先要說明的一點,RxAndroid和RxJava是差不多的東西,隻不過RxAndroid 針對Android平台做了一點調整。那麼RxJava是什麼?在其github上是這樣講的:一個在 Java VM 上使用可觀測的序列來組成異步的、基于事件的程式的庫。這麼講可能還有點繞口,簡單的講實際上最重要的就是異步兩字,RxJava可以簡單的實作異步操作,并且不管邏輯多麼複雜,它始終能夠保持簡潔性。

通常在Android中,非UI線程是不能更新UI界面的,而一些耗時的操作我們又不能放在UI線程,否則會導緻界面卡頓。這種情況下,我們就需要切換線程來實作,即Handler和AsyncTask來實作,但是這兩種都有個缺陷,代碼非常多,非常雜,可讀性非常差。是以,RxJava出現了,它能夠兩行代碼就實作線程切換,非常的簡單,使用起來就會讓人感覺很爽,再也不用為異步操作寫如此繁重的代碼了。

RxJava基本用法

RxJava最核心的兩個東西是Observables(被觀察者,事件源)和Observer/Subscriber(觀察者),還有将他們聯系在一起的操作subscribe(訂閱)。當被觀察者發生變化時觀察者能即使做出相應,就好像我們的按鈕事件一樣:

button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                
            }
        });
           

在這裡button就是被觀察者,OnClickListener就是觀察者,setOnClickListener這個方法就相當于訂閱操作,當button被按下時,OnClickListener監聽到變化,調用OnClick做出反應,RxJava實作的就是類似這樣的一個過程。注意這裡的觀察者有兩種Observer,Subscriber,這兩個其實是差不多的,Subscriber是對Observer的一種擴充,内部增加了OnStart方法,在事件未發送之前訂閱,用于做一些準備工作,并且還有unsubscribe()用于取消訂閱。

讓我們來看一下ObServer的内部實作:

public interface Observer<T> {

    void onCompleted();

    void onError(Throwable e);

    void onNext(T t);

}

           

可以看到ObServer本身是一個接口,内部有onNext(T t)方法:觀測到所檢測的被觀察者有變化時做出相應反應。onCompleted()方法:RxJava 規定,當不會再有新的 onNext() 發出時,需要觸發 onCompleted() 方法作為标志。onCompleted():事件隊列發生異常,要調用的方法。我們在定義一個觀察者的時候,需要實作這些方法,來完成事件隊列。

觀察者有了,那麼被觀察者Observables怎麼建立呢,RxJava提供了一系列操作符供我們調用,其中就有很多建立型操作符,舉個例子,建立一個Observables,發出hello world字元串給觀察者:

Observable<String> myObservable = Observable.create(  
    new Observable.OnSubscribe<String>() {  
        @Override  
        public void call(Subscriber<? super String> sub) {  
            sub.onNext("Hello, world!");  
            sub.onCompleted();  
        }  
    }  
);  
           

既然有了Observables,那我們就可以根據這個Observables建立一個觀察者了,如下:

Observer<String> TestObserver=new Observer<String>() {
        @Override
        public void onCompleted() {
            
        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onNext(String s) {
                Log.i(TAG,s);
        }
    }
           

這樣我們就可以愉快的訂閱了:

myObservable.subscribe(TestObserver);
           

這樣,一個簡單的RxJava訂閱流程就完成了。這裡可能很多人就有疑問了,關鍵的異步呢,展現在哪了?其實這個例子可能不是很明顯,因為被觀察者并不是一個耗時線程,不能很直覺的展現異步。如果myObservable這是一個異步任務,比如網絡請求,那麼我們訂閱之後,TestObserver會一直監聽myObservable是否有傳回,如果有,那麼就做出響應,本質是一樣的。

###RxJava的操作符

RxJava一個強大的地方在于它的異步,另外一個強大的地方就在于它提供了強大的操作符支援。這裡說明一下幾個常用的操作符:

  • ceate操作符
Observable<String> myObservable = Observable.create(  
    new Observable.OnSubscribe<String>() {  
        @Override  
        public void call(Subscriber<? super String> sub) {  
            sub.onNext("Hello, world!");  
            sub.onCompleted();  
        }  
    }  
);
           

ceate操作符建立一個被觀察者,在call方法裡持有一個觀察者Subscriber參數,當這個Observable被訂閱時,執行觀察者相應的方法。

  • just操作符
Observable<String> myObservable = Observable.just("Hello, world!");  
           

上面的代碼可以用這一句話,代替。just操作符的功能就是将一個對象轉化為Observable。

  • from操作符
Observable<String> myObservable = Observable.from("Hello"," world!");  
           

既然有了将單一對象轉化為Observable的操作符,那麼必須要有将多個對象轉化為Observable的操作符,那就是from,from接收一個對象數組,然後逐一發射給觀察者。

現在,用一個例子來說明其他操作符,比如我們有這樣一個方法,根據學生姓名關鍵字查詢學生清單,傳回一個Observable。

Observable<List<Student>> query(String name); 
           

然後我們的需求是一個一個的輸出學生姓名,實作如下:

query("王").subscribe(list -> {
for(Student student:list){
      Log.i(TAG,student.getName());
});
           
  • flatMap操作符
query("王").flatMap(list -> Observable.from(list)) 
                 .subscribe(student ->Log.i(TAG,student.getName());
);
           

上面的例子用flatMap操作符,就可以變得很簡潔,flatMap操作符的功能是接收一個接收一個Observable的輸出作為輸入,同時輸出另外一個Observable,通常是接收一個list,然後逐一發送list的元素。比如這邊的Student數組,變成了逐一發送student的Observable。

  • Map操作符
query("王").flatMap(list -> Observable.from(list)) 
                  .Map(student->return student.getGrade())
                 .subscribe(grade->Log.i(TAG,grade+"");
);
           

現在我們隻想輸出每個學生的成績,我們就需要Map操作符,它的功能是接收一種類型的Observable,轉化為另外一種Observable,比如這邊的Student類型轉化為了Int型的Observable。

query("王").flatMap(list -> Observable.from(list)) 
                  .Map(student->return student.getGrade())
                 .subscribe(grade->Log.i(TAG,grade+"");
);
           
  • filter操作符
query("王").flatMap(list -> Observable.from(list)) 
                  .Map(student->return student.getGrade())
                  .filter(grade->grade>80)
                 .subscribe(grade->Log.i(TAG,grade+"");
);
           

顧名思義filter操作符就是過濾用的,相當于加個判斷條件,比如這邊的就是加上分數大于80的條件.

  • take操作符
query("王").flatMap(list -> Observable.from(list)) 
                  .Map(student->return student.getGrade())
                  .filter(grade->grade>80)
                  .take(5)
                 .subscribe(grade->Log.i(TAG,grade+"");
);
           

take操作符的功能是限定個數,比如這邊的功能就是限定我最多需要5個成績。

  • doOnNext操作符
query("王").flatMap(list -> Observable.from(list)) 
                  .Map(student->return student.getGrade())
                  .filter(grade->grade>80)
                  .take(5)
                  .doOnNext(grade->save(grade))
                 .subscribe(grade->Log.i(TAG,grade+"");
);
           

doOnNext()允許我們在每次輸出一個元素之前做一些額外的事情,比如這裡的我們用來儲存成績。

  • subscribeOn/observeOn操作符
query("王").flatMap(list -> Observable.from(list)) 
                  .Map(student->return student.getGrade())
                  .filter(grade->grade>80)
                  .take(5)
                  .doOnNext(grade->save(grade))
                  .subscribeOn(Schedulers.io())
                  .observeOn(AndroidSchedulers.mainThread())
                 .subscribe(grade->Log.i(TAG,grade+"");
);
           

這兩個操作符一般都是成對出現的,他們的功能就是切換線程。subscribeOn是指定被觀察者的線程,observeOn是指定觀察者的線程。比如這個例子中前面的訂閱的工作在IO線程做,後面的列印功能在主線程做。

  • 小結

    怎麼樣,看起來我好像做了很多事情,又有判斷資料,又有儲存資料,又有選取資料,關鍵還有線程切換,然而,我實際上就寫了那麼一點代碼,看起來是不是酷!這就是RxJava的魅力所在。

RxAndroid

一開始說了,RxAndroid其實跟RxJava是差不多的,但是總歸還是有一點變化的。比如Android上會有生命周期的問題,可能會導緻記憶體洩漏:Observable持有Context導緻的記憶體洩露。在這個問題上,我們的解決方法是這樣的:

private Subscription mTestSubscription= Subscriptions.empty();

public void test(){
mTestSubscription=myObservable.subscribe(TestObserver);
}
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mTestSubscription != null && !mTestSubscription.isUnsubscribed())        {
            mTestSubscription.unsubscribe();
        }

    }
           

就是在訂閱的時候,用一個Subscription來儲存它,然後在退出這個Activity的時候取消訂閱。

另外還有一些專門為Android設計的RxView,比如以下防抖動的View:

RxView.clicks(btn_click)
        .throttleFirst(3, TimeUnit.SECONDS)
        .subscribe();
           

總結

終于是把這八篇文章寫完了!MVP+Retrofit+dagger2+RxAndroid這套架構真的是很不錯的一套架構,希望越來越多的人使用它吧!