rxjava筆記(1)
rxjava的基礎概念
觀察者模式於釋出-訂閱模型
rxjava有四個基礎概念
- Observable 被觀察物件
- Observer 觀察者物件
- subscribe 訂閱
- 事件 事件回撥,包括onNext、onError、onCompleted
rxjava中事件的概念
-
onCompleted():
事件佇列完結,不再有onNext()發出時,需要觸發onCompleted()方法作為完結標誌 -
onError(Throwable e):
事件佇列異常,同時該事件佇列終止,在同一個事件流中,onError和onCompleted只能存在一個 -
onNext(T param):
普通的事件回撥
rxjava的基本實現
-
建立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"); } };
-
建立Observable物件
Observable<String> observable = Observable.create(subscriber1 -> { System.out.println("call"); subscriber1.onNext("sss"); subscriber1.onNext("sss1"); subscriber1.onCompleted(); });
-
訂閱過程,呼叫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的操作符
-
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並進行列印
-
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操作符,程式碼十分簡潔
-
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
相關文章
- RxJava 學習筆記 -- 基礎知識RxJava筆記
- RxJava2操作符學習筆記RxJava筆記
- RxJava 學習筆記 -- 變換操作符RxJava筆記
- RxJava 學習筆記 -- 過濾操作符RxJava筆記
- 筆記1筆記
- RxJava2.X 學習筆記 -- 建立操作符RxJava筆記
- jvm筆記1JVM筆記
- Java筆記1Java筆記
- Day 1 筆記筆記
- OkHttp+Retrofit+Dagger2+RxJava+MVP架構 學習筆記HTTPRxJavaMVP架構筆記
- 學習筆記1筆記
- 陣列筆記1陣列筆記
- 閱讀筆記1筆記
- 學習筆記-1筆記
- python學習筆記(1Python筆記
- Vue學習筆記1Vue筆記
- noip刷題筆記1筆記
- HTTP快取筆記(1)HTTP快取筆記
- swift學習筆記《1》Swift筆記
- django專案筆記1Django筆記
- HTML學習筆記1HTML筆記
- python基礎筆記1Python筆記
- ADworld學習筆記(1)筆記
- Spring筆記(1) - 工廠Spring筆記
- html+CSS筆記(1)HTMLCSS筆記
- flex:1學習筆記Flex筆記
- python入門筆記1Python筆記
- 網路層筆記(1)筆記
- 1-3節筆記筆記
- express 的使用筆記1Express筆記
- git學習筆記 1Git筆記
- git學習筆記1Git筆記
- Day1-Markdown筆記筆記
- SLAM學習筆記(1)SLAM筆記
- golang 學習筆記1Golang筆記
- 《專案管理》-筆記1專案管理筆記
- HTML學習筆記(1)HTML筆記
- effective C++筆記1C++筆記
- 21JavaScript筆記(1)JavaScript筆記