RxJava用法入門及操作符講解,簡單易懂

在看本文之前,假如你已經看過一些Rxjava的介紹,有了大致瞭解,但是仍然看不懂RxJava代碼,並且對它的使用場景心存疑惑,那麼本篇文章是適合你的。

RxJava的學習還是有一定門檻的,難度在於理解它的思維方式,和各種操作符的用處。本篇文章從最基礎的RxJava示例來講解,說明RxJava的基本使用及基礎操作符的作用。

注:本篇文章的RxJava,指的是RxJava1,其他版本的操作符和用法可能會有一些變化。

本篇目錄

  • 前言:RxJava的一些介紹
  • 得到Observable被觀察者對象
  • 得到Observer觀察者對象
  • 實現觀察訂閱
  • RxJava實例講解
  • Retrofit+RxJava用法示例

前言:RxJava的一些介紹

首先要了解,RxJava是基於觀察者模式的,簡而言之就是觀察者訂閱了被觀察者,然後被觀察者產生的數據變化會通知到觀察者,觀察者從而作出反應。這裏就不多做講解了。在Android裏,觀察者模式的場景非常多,比如OnClickListener,比如EventBus等。

那麼RxJava能幹嘛呢?對入門來說,只要是“拿數據,做處理”這樣的流程,都可以用RxJava實現。比如Retrofit網絡請求經常搭配RxJava來實現。甚至打印一個字符串列表也可以用RxJava實現,只要你不嫌它大材小用。

在RxJava裏,觀察者用Observer類或者Subscriber類表示,其中後者是前者的實現類,兩者用法基本相同。觀察者就是處理數據的角色。
而被觀察者用Observable類表示,它是產生數據的角色。

一、首先我們來看下如何得到一個Observable對象,也就是被觀察者。

得到Observable有下面幾種常用方法:

1.Observable.create(xxx)

這裏的xxx爲Observable.OnSubscribe對象,即訂閱事件發生的時候,用於產生數據的對象。

Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("1.....");
                subscriber.onNext("2.....");
                subscriber.onNext("3.....");
                subscriber.onCompleted();
            }
        });

這個數據源產生的數據,就是三個字符串。

2.Observable.from(yyy)

這裏的yyy爲數組,集合,或者Future對象

List<String> list=new ArrayList<>();
        list.add("11111");
        list.add("22222");
        list.add("33333");
        list.add("444444444");
Observable observable = Observable.from(list);

同樣,這個observable對象所能產生的數據也是四個字符串。

3.Observable.just(x,y,z…)

這裏的x,y,z…可以是不同類型的數據。

Observable observable = Observable.just(1,2,3,4,5);

上例這個observable能產生1~5的數字。

二、再來看下如何得到一個觀察者對象(Subscriber或者Observer)

Subscriber<String> subscriber = new Subscriber<String>() {
    @Override
    public void onCompleted() {
       Log.d("test", "onCompleted");
    }

    @Override
    public void onError(Throwable e) {
        Log.d("test", "onError");
    }

    @Override
    public void onNext(String s) {
        Log.d("test", "onNext:"+s);
    }
};
Observer<String> observer = new Observer<String>() {
    @Override
    public void onCompleted() {
        Log.d("test", "onCompleted");
    }

    @Override
    public void onError(Throwable e) {
        Log.d("test", "onError");
    }

    @Override
    public void onNext(String s) {
        Log.d("test", "onNext:"+s);
    }
};

上面實現了兩種觀察者對象,Subscriber和Observer對象所要實現的抽象方法是一樣的。
這裏我們定義此觀察者處理的數據類型爲String類型。實際可根據需求來。按上面這樣得到的觀察者對象,能做什麼呢?
onNext(String s):用於處理數據。
onCompleted():數據全部處理完成,會走到這裏。
onError(Throwable e):數據處理過程出錯,會走這裏。

三、實現訂閱

上面兩步已經得到了被觀察者和觀察者對象,還差一步,就是確立訂閱關係:

observable.subscribe(observer);

或者

observable.subscribe(subscriber);

看上面這兩行代碼會發現,在RxJava裏,訂閱關係是被觀察者(observable)訂閱了觀察者(observer),與我們平時的理解相反。
其實Rxjava這麼寫只是爲了鏈式調用比較方便。真正subscribe()方法的源碼實現裏,仍然是觀察者訂閱了被觀察者。

實際使用中,還可以通過observable.subscribe(new Action0(){…})這樣的方式,即不必定義觀察者,而是通過Action0這樣的類包裝得到。下面會有例子。

四、實例解析

把上面三步用鏈式調用連接起來,完整的例子如下:
例1:打印字符串基本示例

Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        subscriber.onNext("str1");
        subscriber.onNext("str2");
        subscriber.onNext("str3");
        subscriber.onCompleted();
    }
}).subscribe(new Subscriber<String>() {
    @Override
    public void onCompleted() {
        Log.d("test", "onCompleted");
    }

    @Override
    public void onError(Throwable e) {
        Log.d("test", "onError");
    }

    @Override
    public void onNext(String s) {
        Log.d("test", "onNext:"+s);
    }
});

運行結果:

D/test: onNext:str1
D/test: onNext:str2
D/test: onNext:str3
D/test: onCompleted

這個例子實現的功能很簡單,就是依次打印三個字符串,完成後再打印"onCompleted"。如果流程中出了錯誤,則會打印"onError"。

例2:流程前後加入額外處理的示例
subscribe()方法傳入的可以是Subscriber對象,Observer對象,或者Action1對象。

List<String> list=new ArrayList<>();
list.add("11111");
list.add("22222");
list.add("33333");
list.add("44444");
Observable.from(list)
        .subscribe(new Action1<String>() {
    @Override
    public void call(String s) {
        Log.d("test", "call:"+s);
    }
});

同樣功能很簡單,就是依次打印四個字符串。

如果想在打印前後做一些額外處理,怎麼辦呢?可以像下面這樣改:

List<String> list=new ArrayList<>();
list.add("11111");
list.add("22222");
list.add("33333");
list.add("44444");
Observable.from(list)
	//處理前的操作
    .doOnSubscribe(new Action0() {
        @Override
        public void call() {
            Log.d("test", "doOnSubscribe");
        }
    })
    //處理完成後的操作
    .doOnCompleted(new Action0() {
        @Override
        public void call() {
            Log.d("test", "doOnCompleted");
        }
    })
    //正式處理的操作
    .subscribe(new Action1<String>() {
		@Override
		public void call(String s) {
			Log.d("test", "call:"+s);
		}
	});

上面加上了doOnSubscribe和doOnCompleted操作,用於在正式處理前後進行額外處理。
類似地,在流程發生錯誤,或者終止等時機,RxJava都有對應的方法用於處理。

還可以看到,上面出現了Action0和Action1兩個類,它們有什麼區別呢?
Action0的call()不會傳入參數,而Action1的call()會傳入一個參數。類似地還有Action2,Action3,Action4等等。

運行結果:

D/test: doOnSubscribe
D/test: call:11111
D/test: call:22222
D/test: call:33333
D/test: call:44444
D/test: doOnCompleted

例3:數據處理前的篩選變換

Observable.just(1,2,3,4,5)
          .filter(new Func1<Integer, Boolean>() {
              @Override
              public Boolean call(Integer integer) {
                  return integer%2==0;
              }
          })
          .subscribe(integer -> Log.d("test", "call:"+integer));

這裏有個操作符filter,顧名思義是用來篩選數據的。而Func1這個類,用於實現具體的處理邏輯,它和Action1這個類的不同點在於有返回值。

這個例子的功能是篩選出能被2整除的數字,運行結果如下:

D/test: call:2
D/test: call:4

再看一個常用操作符,map

Observable.just(1,2,3,4,5)
        .map(new Func1<Integer, Integer>() {
            @Override
            public Integer call(Integer integer) {
                return integer*2;
            }
        })
        .subscribe(integer -> Log.d("test", "call:"+integer));

map操作符的作用是對數據進行統一的處理。在本例中是對各個數字乘以2。

運行結果如下:

D/test: call:2
D/test: call:4
D/test: call:6
D/test: call:8
D/test: call:10

還有其它各種處理數據的操作符,如得到數據的前幾位,後幾位,排序等。你能想到的各種常用處理,RxJava基本都有對應的操作符。

另外這個例子中使用了lambda表達式,簡化了代碼。

例4:線程的切換示例

使用RxJava可以很方便地進行線程切換,每一步操作都可以切換線程。如下例:

Observable.just(1, 2, 3, 4) // IO 線程,由第一個 subscribeOn() 指定
    .subscribeOn(Schedulers.io())
    .observeOn(Schedulers.newThread())
    .map(mapOperator) // 新線程,由上一行的 observeOn() 指定
    .observeOn(Schedulers.io())
    .map(mapOperator2) // IO 線程,由由上一行的 observeOn() 指定
    .observeOn(AndroidSchedulers.mainThread) 
    .subscribe(subscriber);  // Android 主線程,由由上一行的 observeOn() 指定

切換線程可以使用subscribeOn和observeOn兩個操作符。這兩個有什麼區別呢?

subscribeOn傳入的的是被觀察者,即數據源產生數據時所在的線程。
observeOn傳入的是處理數據所在的線程。

如果鏈式調用中,出現了多個subscribeOn,則數據源產生數據的線程是首個subscribeOn指定的線程。

而每調一次observeOn傳入不同的線程,下一步的數據操作就會變到該線程裏。

可參考扔物線的RxJava講解

五、最後,貼上Retrofit+RxJava使用示例:

service.login(phone, password)//獲取Observable對象
        .subscribeOn(Schedulers.newThread())// 定義登錄操作(獲取Observable對象)在新的線程進行
        .observeOn(Schedulers.io())//請求完成後在io線程中執行保存用戶信息
        .doOnNext(new Action1<UserInfo>() {
            @Override
            public void call(UserInfo userInfo) {
                saveUserInfo(userInfo);//保存用戶信息到數據庫
            }
        })
        .observeOn(AndroidSchedulers.mainThread())//最後在主線程中執行
        .subscribe(new Subscriber<UserInfo>() {
            @Override
            public void onCompleted() {
                //操作完成
            }

            @Override
            public void onError(Throwable e) {
                //請求失敗
            }

            @Override
            public void onNext(UserInfo userInfo) {
                //請求成功,顯示用戶信息,在主線程
				showUserInfo();
            }
        });
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章