rxjava筆記(1)

weixin_33850890發表於2016-12-13

rxjava的基礎概念

觀察者模式於釋出-訂閱模型
rxjava有四個基礎概念

  1. Observable 被觀察物件
  2. Observer 觀察者物件
  3. subscribe 訂閱
  4. 事件 事件回撥,包括onNext、onError、onCompleted

rxjava中事件的概念

  • onCompleted(): 事件佇列完結,不再有onNext()發出時,需要觸發onCompleted()方法作為完結標誌
  • onError(Throwable e): 事件佇列異常,同時該事件佇列終止,在同一個事件流中,onError和onCompleted只能存在一個
  • onNext(T param): 普通的事件回撥

rxjava的基本實現

  1. 建立Observer

    直接new一個Observer介面

     Observer<String> observer = new Observer<String>() {
             @Override
             public void onCompleted() {
                 System.out.println("onCompleted");
             }
    
             @Override
             public void onError(Throwable e) {
                     System.out.println(e.getMessage());
             }
    
             @Override
             public void onNext(String s) {
                     System,out.println(s);
             }
         };
    

    或者new一個rxjava中實現了Observer介面的Subscribe抽象類

    Subscriber<String> subscriber = new Subscriber<String>() {
             public void onCompleted() {
                 System.out.println("onCompleted");
             }
    
             public void onError(Throwable e) {
                 System.out.println(e.getMessage());
             }
    
             public void onNext(String s) {
                 System.out.println(s + " on onNext");
             }
         };
    
  2. 建立Observable物件

    Observable<String> observable = Observable.create(subscriber1 -> {
            System.out.println("call");
            subscriber1.onNext("sss");
            subscriber1.onNext("sss1");
            subscriber1.onCompleted();
        });
    
  3. 訂閱過程,呼叫subscribe方法

    observable.subscribe(subscriber);
    

通過原始碼可以發現,subscribe方法最後都會呼叫

Subscription subscribe(Subscriber<? super T> subscriber)

這個方法,所以第一步在建立觀察者物件的時候,即使使用Observer,最終都會轉換為Subscriber物件。
這個方法的核心步驟為:

subscriber.onStart();  //可選的準備方法
hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);  //Observable被訂閱,發出事件流
return Subscriptions.unsubscribed();  //取消訂閱

通過檢視Subscriber的原始碼可以發現,它相比Observer多出了2個重要的方法:

  • onStart()
    在事件發出之前作一些準備工作,預設方法實現為空
  • unSubscribe()
    取消訂閱,釋放Observalbe對Subscribe的引用,防止記憶體洩漏

rxjava的常用操作符

記錄一下自己學習的幾個rxjava的操作符

  1. map

    將事件物件轉換為另一個物件,例如

    Observable.from(strs)
                .map(new Func1<String, Integer>() {
                    @Override
                    public Integer call(String s) {
                        return s.hashCode();
                    }
                })
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        System.out.println(integer);
                    }
                });
    

    結合lambda表示式就可以寫成為

    Observable.from(strs)
                .map(s -> s.hashCode())
                .subscribe(integer -> System.out.println(integer));
    

    程式碼非常的簡潔。這段程式碼獲取了每個string的hashcode並進行列印

  2. flatMap

    先記下這裡示例程式碼中的需要使用物件

    static class Student {
        List<String> courses;  //課程
    
        public Student() {
        }
    
        public void setCourses(List<String> courses) {
            this.courses = courses;
        }
    
        public List<String> getCourses() {
            return courses;
        }
    }
    

    有些時候,map並能滿足我們的所有需求,比如我使用map,獲取到的物件是一個List,這個時候,我們在遍歷list的時候就要在回撥方法裡面寫for迴圈,就類似這樣:

    Observable.from(students)
                .map(student -> student.getCourses()).subscribe(strings -> {
                    for (String course :
                            strings) {
                        System.out.println(course);
                    }
                });
    

    如果我需要再把每一個course放入事件流,那麼就又需要自己去create Observer,非常的不簡潔。於是,我們可以使用flatMap操作符,flatMap操作符可以把事件物件轉換為另一個物件的Observable
    示例程式碼如下:

    Observable.from(students)
                .flatMap(new Func1<Student, Observable<String>>() {
                    @Override
                    public Observable<String> call(Student student) {
                        return Observable.from(student.getCourses());
                    }
                })
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        System.out.println(s);
                    }
                });
    

    配合lamdba寫成

     Observable.from(students)
                .flatMap(student -> Observable.from(student.getCourses()))
                .subscribe(s -> System.out.println(s));
    

    即使需要繼續下去,也可以繼續使用flatMap操作符,程式碼十分簡潔

  3. compose操作符
    通過原始碼可以看到,map/flatMap操作符的實現其實是通過left()實現的,在rxjava中,除了left,還有一個變換叫ompose(Transformer)
    這個操作符針對自身進行變換,事件序列並不會改變
    例如原先的程式碼中需要多個left()變換:

    observable1
    .lift1()
    .lift2()
    .subscribe(subscriber1);
    

observable2
.lift1()
.lift2()
.subscribe(subscriber2);
observable3
.lift1()
.lift2()
.subscribe(subscriber3);
observable4
.lift1()
.lift2()
.subscribe(subscriber1);
```

這段程式碼簡單封裝後可以寫成:

```
private Observable liftAll(Observable observable) {
return observable
    .lift1()
    .lift2()

}
liftAll(observable1).subscribe(subscriber1);
liftAll(observable2).subscribe(subscriber2);
liftAll(observable3).subscribe(subscriber3);
liftAll(observable4).subscribe(subscriber4);
```
這段程式碼看起來比之前的程式碼舒服很多,但是封裝了observable,感覺不是很靈活,於是程式碼可以改寫成:

```
class AllLeftTransformers implements Observable.Transformer<Integer, String> {
    @Override
    public Observable<String> call(Observable<Integer> observable) {
        return observable.left1().left2();
    }

}
AllLeftTransformers liftAll = new AllLiftTransfomers();
//訂閱事件
observable1.compose(leftAll).subscriber(subscribe1);
observable2.compose(leftAll).subscriber(subscribe2);
observable3.compose(leftAll).subscriber(subscribe3);
observable4.compose(leftAll).subscriber(subscribe4);
```
這樣相對於自己封裝的優勢就在於,不用把Observable封裝,並不會減少Observable的靈活性

rxjava的執行緒排程

rxjava內建了執行緒排程(scheduler)
示例程式碼:

Observable.from(array)
                .observeOn(Schedulers.immediate())
                .subscribeOn(Schedulers.io())
                .subscribe(i -> System.out.println(i + ""));

上面程式碼的意思就是觀察在當前執行緒,訂閱事件發生在io執行緒
關於rxjava的Schedulers裡面常見的執行緒有如下幾種

  • Schedulers.immediate() 當前執行緒
  • Schedulers.io() io執行緒
  • Schedulers.newThread() 新的執行緒
  • Schedulers.computation() 計算執行緒,即CPU密集的執行緒
    其中rxAndroid裡面還有一個AndroidSchedulers.mainThread(),表示Android的ui執行緒

再比如比較經典的,在Android中請求網路資料:

getId()
    .observeOn(AndroidSchedulers.mainThread())
    .subscribeOn(Schedulers.io())
    .subscriber(user->userView.setId(user.id));

其中

  • 觀察者表示的就是ui介面,使用在android主執行緒進行
  • 被觀察者應該是觀察是否發生網路請求獲取資料,所以訂閱事件發生在io執行緒2

相關文章