RxJava2.x學習文檔
CSDN:https://blog.csdn.net/chenzhen200638/article/details/81569036
用一句話描述RxJava的本質:
- RxJava採用觀察者模式,實現了數據發射(emitter)和數據接收並消費(consumer)響應式開發模式,並能靈活切換任務線程。
觀察者模式 RxJava 以觀察者模式爲骨架,在 2.0 中依舊如此,不過此次更新中,出現了兩種觀察者模式:
- Observable ( 被觀察者 ) / Observer ( 觀察者 )
- Flowable (被觀察者)/ Subscriber (觀察者)
在 RxJava 2.x 中,Observable 用於訂閱 Observer,不再支持背壓(1.x 中可以使用背壓策略),而 Flowable 用於訂閱 Subscriber , 是支持背壓(Backpressure)的。
一、Observable 的創建
1.創建Observable被觀察者對象,並給訂閱者發射數據,獲得數據後給界面展示.
public Observable queryStudentWithObservable(int age){
return Observable.create( (ObservableOnSubscribe<Student>) e -> {
Realm realm = Realm.getDefaultInstance();
Student student = null;
try {
realm.beginTransaction();
student = realm.where(Student.class).equalTo("age", age).findFirst();
realm.commitTransaction();
} catch (Exception ex) {
ex.printStackTrace();
}finally {
if(student != null){
e.onNext(student);
}else{
e.onError(new Throwable("沒有查到數據!"));
}
}
});
}
- 訂閱消息,並顯示查詢到的學生數據.
public void queryStudentWithObservable(){
container.removeAllViews();
RealmService.getRealmService().queryStudentBy(15).subscribe(
student-> container.addView(buildTextView(student.toString())),
throwable-> Toast.makeText(this,throwable.toString(),Toast.LENGTH_LONG).show())
.dispose();
}
來看看subscibe的源碼實現, subscribe的參數有兩個:Consumer onNext,Consumer onError;
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final Disposable subscribe(
Consumer<? super T> onNext,
Consumer<? super Throwable> onError,
Action onComplete, Consumer<? super Disposable> onSubscribe) {
... ...
//核心代碼,實際上就是新構造了一個LambdaObserver定閱數據源;
LambdaObserver<T> ls = new LambdaObserver<T>(onNext, onError, onComplete, onSubscribe);
subscribe(ls);
return ls;
}
二、Flowable 的創建
1.創建Flowable被觀察者對象,並給訂閱者發射數據,獲得數據後給界面展示.
public Flowable<Student> queryStudentWithFlowable(int age){
return Flowable.create( e -> {
Realm realm = Realm.getDefaultInstance();
Student student = null;
try {
realm.beginTransaction();
student = realm.where(Student.class).equalTo("age", age).findFirst();
realm.commitTransaction();
} catch (Exception ex) {
ex.printStackTrace();
}finally {
if(student != null){
e.onNext(student);
}else{
e.onError(new Throwable("沒有查到數據!"));
}
}
}, BackpressureStrategy.BUFFER);
}
- 訂閱消息,並顯示查詢到的學生數據.
public void queryStudentWithObservable(){
RealmService.getRealmService().queryStudentWithFlowable(15).subscribe(
student-> container.addView(buildTextView(student.toString())),
throwable-> Toast.makeText(this,throwable.toString(),Toast.LENGTH_LONG).show())
.dispose();
}
三、常用的簡化版的Observer
- 1).在Rxjava2中,Observale和Flowable都是用來發射數據流的。
- 2).我們在實際應用中,很多時候,需要發射的數據並不是數據流的形式,而只是一條單一的數據,或者一條完成通知、或者一條錯誤的通知。
- 3).在這種場景下,我們再使用Observable或者Flowable就顯得有點大材小用。於是,爲了滿足這種單一數據或通知的使用場景,便出現了Observable的簡化版: Single、Completable、Maybe。
3.1 Single
應用場景: 只發射一條單一的數據,或者一條異常通知,不能發射完成通知,其中數據與通知只能發射一個結果.
實例: 查詢數據庫,成功則更新UI,失敗則提示沒有查詢到數據.
- Single.fromCallable(emitter->{})
或者
- Single.create(emitter->{});
/**
*創建一個Single的數據源,根據年紀參數查詢學生數據;
**/
public Single<Student> findStudentBy(int age) {
return Single.fromCallable(() -> {
Realm realm = Realm.getDefaultInstance();
Student student = null;
try {
realm.beginTransaction();
student = realm.where(Student.class).equalTo("age", age).findFirst();
realm.commitTransaction();
} catch (Exception ex) {
ex.printStackTrace();
}
if(student == null){
throw new Exception("沒有查到數據!");
}
return student;
});
}
/**
*查詢年紀爲15歲的學生
**/
public void singleQuerySample() {
container.removeAllViews();
Single<Student> s15 = RealmService.getRealmService().findStudentBy(15);
s15.subscribe(
student -> container.addView(buildTextView(student.toString())),
error -> Toast.makeText(
MainActivity.this,
error.toString(),
Toast.LENGTH_LONG).show());
}
3.2 Completable
應用場景: 只發射一條完成通知,或者一條異常通知,不能發射數據,其中完成通知與異常通知只能發射一個
例子:添加學生數據,不關注成功失敗,只關注事件完成與否。
- Completeble.fromAction(emitter->{})
或者 - Completeble.create(emitter->{})
/**
* 添加學生數據,創建一個Completeble對象;
**/
public Completable addStudent(Student student) {
//注意,這裏是通過fromAction來生成一個Completeble,即只關注單一的動作是否完成.
return Completable.fromAction(() -> {
Realm realm = Realm.getDefaultInstance();
try {
realm.executeTransaction(r -> {
Student s = realm.createObject(Student.class, UUID.randomUUID().toString());
s.setName(student.getName());
s.setAddress(student.getAddress());
s.setAge(student.getAge());
realm.copyFromRealm(s);
});
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (realm != null) {
realm.close();
}
}
});
}
或者,也可以通過Completeble.create()來創建Completeble.
public Completable addStudent(Student student) {
return Completable.create( e -> {
Realm realm = Realm.getDefaultInstance();
try {
realm.executeTransaction(r -> {
Student s = realm.createObject(Student.class, UUID.randomUUID().toString());
s.setName(student.getName());
s.setAddress(student.getAddress());
s.setAge(student.getAge());
realm.copyFromRealm(s);
});
//結束業務流程,發送通知完成了;
e.onComplete();
} catch (Exception ex) {
ex.printStackTrace();
//發生異常,發送一個異常通知;
e.onError(ex);
} finally {
if (realm != null) {
realm.close();
}
}
});
}
然後在Activity中,調用這個接口添加學生數據,完成添加動作之後,更新數據和ui.
/**
*Activity中: 構造學生數據
**/
public void buildStudentDatas() {
Student a = new Student();
a.setAge(14);
a.setAddress("中國北京");
a.setName("周浩");
Student b = new Student();
b.setAge(15);
b.setAddress("深圳小牛在線");
b.setName("陳真");
Student c = new Student();
c.setAge(16);
c.setAddress("中國上海");
c.setName("文忠湖");
//每添加一個學生的數據後,查詢並更新ui.
RealmService.getRealmService().addStudent(a).subscribe(this::queryStudent);
RealmService.getRealmService().addStudent(b).subscribe(this::queryStudent);
RealmService.getRealmService().addStudent(c).subscribe(this::queryStudent);
}
/**
*查詢所有學生數據,並更新界面
*/
public void queryStudent() {
container.removeAllViews();
RealmService.getRealmService().findAllStudent()
.subscribe(students -> {
for (Student s : students) {
container.addView(buildTextView(s.toString()));
}
});
}
3.3 Maybe
應用場景: 可發射一條單一的數據,以及發射一條完成通知,或者一條異常通知(onComplte() 和 onError() 只能發射其中一個消息,同時發送的話onComplete()無效),其中完成通知和異常通知只能發射一個,發射數據只能在發射完成通知或者異常通知之前,否則發射數據無效。
例子: 根據年紀來查詢學生數據,查到了發送數據,沒查到要麼發送完成消息,要麼發送異常信息;
public Maybe queryStudentWithMaybe(int age){
return Maybe.create( e -> {
Realm realm = Realm.getDefaultInstance();
Student student = null;
try {
realm.beginTransaction();
student = realm.where(Student.class).equalTo("age", age).findFirst();
realm.commitTransaction();
} catch (Exception ex) {
ex.printStackTrace();
}finally {
if(student != null){
//如果查詢到結果發送數據;
e.onSuccess(student);
}else{
//如果沒有查詢到數據,發送異常消息;
e.onError(new Throwable("沒有查到數據!"));
}
//事件完成發送完成通知;
//e.onComplete();
}
});
}
Activity中接收數據,並在ui中展示結果
public void queryStudentWithMaybe() {
container.removeAllViews();
RealmService.getRealmService().queryStudentWithMaybe(15).subscribe(
student -> container.addView(buildTextView(student.toString())),
error -> Toast.makeText(MainActivity.this, error.toString(), Toast.LENGTH_LONG).show())
.dispose();
}
四、線程切換
4.1 subScribeOn
subscribeOn 用於指定 subscribe() 上游所發生的線程,從源碼角度可以看出,內部線程調度是通過 ObservableSubscribeOn 來實現的。
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> subscribeOn(Scheduler scheduler) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}
4.2 observeOn
observeOn 方法用於指定下游 Observer 回調發生的線程。
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
ObjectHelper.verifyPositive(bufferSize, "bufferSize");
return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
}
4.3 compose 代碼複用
4.3.1、RxJava 內置的線程調度器的確可以讓我們的線程切換得心應手,但其中也有些需要注意的地方。
- 簡單地說,subscribeOn() 指定的就是發射事件的線程,observerOn 指定的就是訂閱者接收事件的線程;
- 多次指定發射事件的線程只有第一次指定的有效,也就是說多次調用 subscribeOn()只有第一次的有效,其餘的會被忽略;
- 但多次指定訂閱者接收線程是可以的,也就是說每調用一次 observerOn(),下游的線程就會切換一次;
4.3.2、RxJava 中,已經內置了很多線程選項供我們選擇,例如有:
- Schedulers.io() 代表io操作的線程, 通常用於網絡,讀寫文件等io密集型的操作;
- Schedulers.computation() 代表CPU計算密集型的操作, 例如需要大量計算的操作;
- Schedulers.newThread() 代表一個常規的新線程;
- AndroidSchedulers.mainThread() 代表Android的主線程
4.3.3、使用compose包裝代碼,重複利用代碼:
相信小夥伴在使用RXJava與Retrofit請求網絡時,都有遇到過這樣的場景,在IO線程請求網絡解析數據,接着返回主線程setData、更新View試圖,那麼也肯定熟悉下面這幾句代碼:
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
如果網絡請求的次數比較少, 作爲一名不拘小節.
但是如果請求網絡的biz次數多起來了,又不想去破環RX的鏈式結構,那麼怎麼辦呢?
其實使用compose操作符每次僅書寫一行代碼就能完成工作線程的切換了!
final Observable.Transformer schedulersTransformer = new Observable.Transformer() {
@Override public Object call(Object observable) {
return ((Observable) observable)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread());
}
};
僅僅通過.compose(schedulersTransformer)行代碼就完成了線程切換.
RetrofitClient.singletonDemoService("http://gank.io/api/random/data/")
.requestNet("福利","1")
.compose(schedulersTransformer)
.subscribe(subscriber);
五、操作符
5.1 map 操作符
Map是RxJava中最簡單的一個變換操作符,它的作用是將上游發送過來的事件都去應用一個函數,讓每一個事件都按照該函數去變化,下游接收到事件時,就變成了變化過後的事件。
例子:把數字轉換成字符串
官方文檔:http://reactivex.io/documentation/operators/map.html
Observable.create(e -> {
e.onNext(1);
e.onNext(2);
e.onNext(3);}
).map( upstream-> "0x"+String.valueOf(upstream))
.subscribe(result-> container.addView(buildTextView(result)));
輸出結果:
0x1
0x2
0x3
5.2 flatMap 操作符
FlatMap,這個操作符和剛纔的Map有什麼區別呢?
FlatMap可以將上游發送過來的數據,變換爲多個數據,然後合併爲一個事件發送到下游。
例子: 所數據源 1, 2, 3變換成多個數據發送;
官方文檔: http://reactivex.io/documentation/operators/flatmap.html
container.removeAllViews();
Observable.create(e -> {
e.onNext(1);
e.onNext(2);
e.onNext(3);}
).flatMap( upstream-> {
List<String> source = new ArrayList<>();
for(int i=0; i<3; i++){
source.add("0x"+ upstream);
}
return Observable.fromIterable(source);
})
.subscribe(result-> container.addView(buildTextView(result)));
輸出結果: 無序輸出
0x1
0x1
0x1
0x2
0x2
0x3
0x3
0x2
0x3
5.3 concatMap 操作符
ConcatMap和FlatMap一樣,只不過一個是有序,一個是無序而已,我們直接把上邊的代碼做一個更改.
container.removeAllViews();
Observable.create(e -> {
e.onNext(1);
e.onNext(2);
e.onNext(3);}
).concatMap( upstream-> {
List<String> source = new ArrayList<>();
for(int i=0; i<3; i++){
source.add("0x"+ upstream);
}
return Observable.fromIterable(source);
})
.subscribe(result-> container.addView(buildTextView(result)));
輸出結果: 有序輸出
0x1
0x1
0x1
0x2
0x2
0x3
0x3
0x3
0x3
5.4 zip 操作符
構建一個 String 發射器 和 Integer 發射器
//創建 String 發射器
private Observable<String> getStringObservable() {
return Observable.create( e->{
e.onNext("A");
e.onNext("B");
e.onNext("C");
});
}
//創建 Integer 發射器
private Observable<Integer> getIntegerObservable() {
return Observable.create(e-> {
e.onNext(1);
e.onNext(2);
e.onNext(3);
e.onNext(4);
e.onNext(5);
});
}
使用 zip 操作符,打包合併兩個事件
private void zip(){
Observable.zip(
getStringObservable(),
getIntegerObservable(),
(string,integer)->string+integer).subscribe(
result-> container.addView(buildTextView(result))
);
}
輸出結果: 多出來的 4,5 被拋棄了,沒有匹配的數據合併;
A1
A2
A3
5.5 interval 操作符
interval操作符是每隔一段時間就產生一個數字,這些數字從0開始,一次遞增1直至無窮大;
public void interval(){
Flowable.interval(1, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result-> container.addView(buildTextView(String.valueOf(result))));
或者
Observable.interval(1, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result-> container.addView(buildTextView(String.valueOf(result))));
}
輸出結果:
0
1
2
3
...
n
利用interval實現倒計時的功能, 倒計時5秒鐘
public void countDown(){
Observable.interval(1, TimeUnit.SECONDS)
.map(source-> 5-source)
.observeOn(AndroidSchedulers.mainThread())
.take(5)
.subscribe(result-> container.addView(buildTextView(String.valueOf(result))));
}
輸出結果:
5
4
3
2
1
5.6 repeat 操作符
該操作符用來重複發送數據源
- repeat( ) 無限重複
- repeat( int time ) 設定重複的次數
private void repeat(){
Observable.just(1,2)
.repeat(2)
.subscribe(result-> container.addView(buildTextView(String.valueOf(result))));
}
輸出結果:
1
2
1
2
5.7 range 操作符
range 發射特定整數序列的 Observable
- range( int start , int end ) start :開始的值 , end :結束的值
private void range(){
Observable
.range( 1 , 5 )
.subscribe(result-> container.addView(buildTextView(String.valueOf(result))));
}
輸出結果:
1
2
3
4
5
5.8 fromArray操作符
由一個數組充當數據源發射到訂閱者
private void fromArray(){
Integer[] items = {0, 1, 2, 3, 4, 5};
Observable
.fromArray(items)
.subscribe(result-> container.addView(buildTextView(String.valueOf(result))));
}
輸出結果:
1
2
3
4
5
5.9 fromIterable操作符
由一個集合充當數據源發射到訂閱者
public void fromIterable(){
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
Observable
.fromIterable(list)
.subscribe(result-> container.addView(buildTextView(String.valueOf(result))));
}
輸出結果:
a
b
c
5.10 delay 操作符
延遲數據源的發射
Observable
.just(1, 2, 3)
.delay(3, TimeUnit.SECONDS) //延遲3秒鐘,然後在發射數據
.subscribe(result-> container.addView(buildTextView(String.valueOf(result))));
六、背壓
6.1 背壓概念
RxJava是一個觀察者模式的架構,當這個架構中被觀察者(Observable)和觀察者(Subscriber)處在不同的線程環境中時,由於者各自的工作量不一樣,導致它們產生事件和處理事件的速度不一樣,這就會出現兩種情況:
- 被觀察者產生事件慢一些,觀察者處理事件很快。那麼觀察者就會等着被觀察者發送事件。
- 被觀察者產生事件的速度很快,而觀察者處理很慢。那就出問題了,如果不作處理的話,事件會堆積起來,最終擠爆你的內存,導致程序崩潰。
需要強調兩點:
- 背壓策略的一個前提是異步環境,也就是說,被觀察者和觀察者處在不同的線程環境中。
- 背壓(Backpressure)並不是一個像flatMap一樣可以在程序中直接使用的操作符,他只是一種控制事件流速的策略。
RxJava2.X中,Observeable用於訂閱Observer,是不支持背壓的,而Flowable用於訂閱Subscriber,是支持背壓(Backpressure)的。
6.2 背壓策略
onBackpressureBuffer:默認情況下緩存所有的數據,不會丟棄數據,這個方法可以解決背壓問題,但是它有像 Observable 一樣的缺點,緩存數據太多,佔用太多內存。
onBackpressureBuffer(int capacity) :設置緩存隊列大小,但是如果緩衝數據超過了設置的值,就會報錯,發生崩潰。
Flowable的三種Backpressure策略:
- BackpressureStrategy.BUFFER
- BackpressureStrategy.DROP
- BackpressureStrategy.LATEST
onBackpressureBuffer()不丟棄數據的處理方式。把上游收到的全部緩存下來,等下游來請求再發給下游。相當於一個水庫。但上游太快,水庫(buffer)就會溢出。
private void backPressure(){
Flowable.interval( 1 , TimeUnit.MILLISECONDS)
.onBackpressureBuffer( 100) //設置緩衝隊列大小爲 1000
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result-> container.addView(buildTextView(String.valueOf(result))));
}
上面代碼運行一段時間後,會報錯:
08-13 11:28:57.262 32675-32675/realm.com.xn.realmdatabase E/AndroidRuntime:
FATAL EXCEPTION: main Process: realm.com.xn.realmdatabase,
PID: 32675 io.reactivex.exceptions.OnErrorNotImplementedException: Buffer is full
通過日誌可以看出,緩衝區已經滿了.
注:onBackpressureLatest就是隻保留最新的事件
七、RxBinding的使用
git地址:https://github.com/JakeWharton/RxBinding
需要的庫清單, 在gradle中添加以下庫
implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
implementation 'com.jakewharton.rxbinding2:rxbinding-support-v4:2.1.1'
implementation 'com.jakewharton.rxbinding2:rxbinding-appcompat-v7:2.1.1'
implementation 'com.jakewharton.rxbinding2:rxbinding-design:2.1.1'
implementation 'com.jakewharton.rxbinding2:rxbinding-recyclerview-v7:2.1.1'
implementation 'com.jakewharton.rxbinding2:rxbinding-leanback-v17:2.1.1'
7.1 防抖處理
- 兩秒鐘之內只取一個點擊事件,防抖操作
RxView.clicks(this.findViewById(R.id.addStudent))
.throttleFirst(2,TimeUnit.SECONDS)
.subscribe(v-> addStudent());
7.2 長按事件
按鈕的長按時間監聽
RxView.longClicks(this.findViewById(R.id.Merge))
.throttleFirst(2,TimeUnit.SECONDS)
.subscribe(v-> merge());
7.3 listView 的點擊事件、長按事件處理
ListView 單擊事件
ListView listView = this.findViewById(R.id.list);
RxAdapterView.itemClicks(listView).subscribe(index-> onItemClick(index));
ListView 長按事件
ListView listView = this.findViewById(R.id.list);
RxAdapterView.itemLongClicks(listView).subscribe(index-> onItemClick(index));
7.4 CheckBox 勾選事件
checkBox = (CheckBox) findViewById( R.id.checkbox );
RxCompoundButton.checkedChanges(checkBox)
.subscribe( status-> {
button.setEnabled(status);
button.setBackgroundResource( status ? R.color.button_yes : R.color.button_no );
}) ;
7.5 搜索聯想功能
搜索的時候,關鍵詞聯想功能 ,debounce()在一定的時間內沒有操作就會發送事件;
實現數據庫根據輸入學生姓名匹配搜索功能
editText = (EditText) findViewById( R.id.editText );
listView = (ListView) findViewById( R.id.listview );
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1 );
listView.setAdapter(adapter);
RxTextView.textChanges(editText)
.debounce( 600 , TimeUnit.MILLISECONDS )
.observeOn( Schedulers.io() )
.map(charSequence->{
//根據輸入的內容,模糊查詢學生信息
List<Student> students =
RealmService.getRealmService().queryStudentBy(charSequence);
return students;
})
.subscribe(new Action1<List<String>>() {
@Override
public void call(List<Student> students) {
adapter.clear();
adapter.addAll(students);
adapter.notifyDataSetChanged();
}
}) ;
八、生命週期控制和內存優化
RxJava使我們很方便的使用鏈式編程,代碼看起來既簡潔又優雅。但是RxJava使用起來也是有副作用的,使用越來越多的訂閱,內存開銷也會變得很大,稍不留神就會出現內存溢出的情況,這篇文章就是介紹Rxjava使用過程中應該注意的事項。
8.1 取消訂閱
String rmName = rmNameTextView.getText().toString();
RealmService.getRealmService()
.deleteStudentBy(rmName)
.subscribe(this::queryStudent)
.dispose();//也可以在onDestroy中銷燬
或者
@Override
protected void onDestroy() {
super.onDestroy();
//取消訂閱
if ( subscription != null ){
subscription.unsubscribe();
}
}
8.2 RxLifecycle 框架的使用
- github地址: https://github.com/trello/RxLifecycle
在android studio 裏面添加引用
compile ‘com.trello:rxlifecycle-components:0.6.1’讓你的activity繼承RxActivity,RxAppCompatActivity,RxFragmentActivity
讓你的fragment繼承RxFragment,RxDialogFragment;下面的代碼就以RxAppCompatActivity舉例
8.2.1 bindToLifecycle 方法
在子類使用Observable中的compose操作符,調用完成Observable發佈的事件和當前的組件綁定,實現生命週期同步。從而實現當前組件生命週期結束時,自動取消對Observable訂閱。
public class MainActivity extends RxAppCompatActivity {
TextView textView ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
//循環發送數字
Observable.interval(0, 1, TimeUnit.SECONDS)
.subscribeOn( Schedulers.io())
//這個訂閱關係跟Activity綁定,Observable 和activity生命週期同步
.compose(this.<Long>bindToLifecycle())
.observeOn( AndroidSchedulers.mainThread())
.subscribe( time->textView.setText( String.valueOf( aLong ) ) );
}
}
上面的代碼是Observable循環的發送數字,並且在textview中顯示出來
- 1.沒加 compose(this.bindToLifecycle()) 當Activiry 結束掉以後,Observable還是會不斷的發送數字,訂閱關係沒有解除
- 2.添加compose(this.bindToLifecycle()) 當Activity結束掉以後,Observable停止發送數據,訂閱關係解除。
8.2.2 bindUntilEvent( ActivityEvent event)
從上面的例子可以看出bindToLifecycle() 方法可以使Observable發佈的事件和當前的Activity綁定,實現生命週期同步。也就是Activity 的 onDestroy() 方法被調用後,Observable 的訂閱關係才解除。那能不能指定在Activity其他的生命狀態和訂閱關係保持同步,答案是有的。就是bindUntilEvent()方法
ActivityEvent.CREATE: 在Activity的onCreate()方法執行後,解除綁定。
ActivityEvent.START:在Activity的onStart()方法執行後,解除綁定。
ActivityEvent.RESUME:在Activity的onResume()方法執行後,解除綁定。
ActivityEvent.PAUSE: 在Activity的onPause()方法執行後,解除綁定。
ActivityEvent.STOP:在Activity的onStop()方法執行後,解除綁定。
ActivityEvent.DESTROY:在Activity的onDestroy()方法執行後,解除綁定。
//循環發送數字
Observable.interval(0, 1, TimeUnit.SECONDS)
.subscribeOn( Schedulers.io())
//當Activity執行Onstop()方法是解除訂閱關係
.compose(this.<Long>bindUntilEvent(ActivityEvent.STOP ))
.observeOn( AndroidSchedulers.mainThread())
.subscribe(time->textView.setText( String.valueOf( aLong ) ));
FragmentEvent 這個類是專門處理訂閱事件與Fragment生命週期同步
public enum FragmentEvent {
ATTACH,
CREATE,
CREATE_VIEW,
START,
RESUME,
PAUSE,
STOP,
DESTROY_VIEW,
DESTROY,
DETACH
}
可以看出FragmentEvent 和ActivityEvent 類似,都是枚舉類,用法是一樣的.