前言
通過前兩篇文章對於RxJava概念,原理及使用的學習,想必各位碼友已經基本掌握RxJava的邏輯與功能了,那麼從這篇文章開始我們來研究RxJava的各類操作符。
什麼是操作符?通過之前的學習,我們發現Observable負責傳送事件,Observer負責接收事件,而這個過程中想要對事件資料做出修改就需要交給操作符來負責啦。主流RxJava中操作符主要分為三類:轉換操作符,過濾操作符,組合操作符。而我個人將用來建立Observable的操作符歸為了一個新型別。本篇我們就來看看常用的建立操作符都有哪些以及如何使用。
建立操作符
Create
上一篇文章的例子中我們已經實踐了create操作符如何使用了,這裡我們介紹一種便捷的建立Observer的方式。
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
for (int i = 0; i < 5; i++) {
subscriber.onNext("xulei" + i);
}
subscriber.onCompleted();
}
}).subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("rx_test", "create:" + s);
}
});複製程式碼
subscribe()的入參使用Action1代替原來的Observer,只需重寫一個call()方法,等同於原Observer中onNext()方法。如果需要onComplete與onError狀態,還可以如下:
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("rx_test", "create:" + s);
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
Log.e("rx_test", "onError:" + throwable.getMessage());
}
}, new Action0() {
@Override
public void call() {
Log.e("rx_test", "onCompleted");
}
});複製程式碼
使用new ActionX代替new Observer,程式碼是不是看起來更加靈活與簡潔呢。
Just
just操作符可將某個或某些物件轉化為Observable物件,並將其發射出去。引數可為一個或多個數字,字串。也可為集合,陣列,Iterate物件等。
Observable.just(1, 2, 3, 4, 5, 6).subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
Log.e("rx_test", "just:數字:" + integer);
//數字或者字串都是單個發射多次
}
});
List<String> stringList = new ArrayList<>();
stringList.add("Hello");
stringList.add("Ha");
stringList.add("RxJava");
Observable.just(stringList).subscribe(new Action1<List<String>>() {
@Override
public void call(List<String> strings) {
Log.e("rx_test", "just:集合:" + strings.toString());
//集合或陣列是直接發射集合整體,不會拆分
}
});複製程式碼
輸出結果:
just:數字:1
just:數字:2
just:數字:3
just:數字:4
just:數字:5
just:數字:6
just:集合:[Hello, Ha, RxJava]複製程式碼
From
from操作符可將某個物件轉化為Observable物件,並且將其發射出去。不同於just,他接收集合或陣列,並可將集合陣列遍歷之後拆分傳送。
List<String> stringList = new ArrayList<>();
stringList.add("Hello");
stringList.add("Ha");
stringList.add("RxJava");
Observable.from(stringList).subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("rx_test", "from:" + s);
}
});複製程式碼
輸出結果:
from:Hello
from:Ha
from:RxJava複製程式碼
Range
range(int start, int count)操作符,根據初始值start,與數量count,發射count次以start為基數依次增加的值。
Observable.range(4, 5).subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
Log.e("rx_test", "range:" + integer);
}
});複製程式碼
輸出結果:
range:4
range:5
range:6
range:7
range:8複製程式碼
Defer
defer操作符功能類似於just操作符,不同之處在於defer只有在呼叫subscribe()方法進行訂閱時才建立Observable,而just操作符在初始化Observable就已經建立了,且只建立一個Observable例項。這裡我們通過與just對比進行實踐。
Action1<String> action1 = new Action1<String>() {
@Override
public void call(String s) {
Log.e("rx_test", s);
}
};
//defer
Observable<String> deferObservable = Observable.defer(new Func0<Observable<String>>() {
@Override
public Observable<String> call() {
Object o = new Object();
return Observable.just("defer:hashCode:" + o.hashCode());
}
});
deferObservable.subscribe(action1);
deferObservable.subscribe(action1);
deferObservable.subscribe(action1);
//just
Observable<String> justObservable = Observable.just("just:hashCode:" + new Object().hashCode());
justObservable.subscribe(action1);
justObservable.subscribe(action1);
justObservable.subscribe(action1);複製程式碼
輸出結果:
defer:hashCode:112449879
defer:hashCode:118897732
defer:hashCode:191664429
just:hashCode:121878114
just:hashCode:121878114
just:hashCode:121878114複製程式碼
由輸出結果我們可以看出defer每次輸出的Observable哈西值是不同的,說明其每subscribe訂閱一次都會建立一個新的Observable,從而可保證Observable中的資料都是最新的。而just只有初始化的時候建立一次Observable。
Interval
interval建立操作符,建立一個Observabel並每隔一段時間週期發射一個由0開始增加的數字。
注意:此Observabel是執行在新的執行緒,所以更新UI需要在主執行緒中訂閱
//每隔100ms發射一個數字,從0自增
Observable.interval(100, TimeUnit.MILLISECONDS) //單位為毫秒
.observeOn(AndroidSchedulers.mainThread())
.take(5) //取前5次事件發射,take為過濾操作符,後期會詳細講
.subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
Log.e("rx_test", "interval:" + aLong);
}
});複製程式碼
輸出結果:
100ms後...
interval:0
100ms後...
interval:1
100ms後...
interval:2
100ms後...
interval:3
100ms後...
interval:4複製程式碼
Timer
timer操作符,建立一個Observable並隔一段時間後發射一個特殊的值,僅發射一次。
注意:此Observabel是執行在新的執行緒,所以更新UI需要在主執行緒中訂閱
//隔1s後發射一個數字
Observable.timer(1, TimeUnit.SECONDS) //單位為秒
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
Log.e("rx_test", "timer:" + aLong);
}
});複製程式碼
輸出結果:
1秒後...
timer:0複製程式碼
Delay
delay操作符,可用於延遲一定時長再傳送事件。
//延遲2秒後發射事件
Observable.just(1, 2, 3)
.delay(2, TimeUnit.SECONDS)
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
Log.e("rx_test", "delay:" + integer);
}
});複製程式碼
輸出結果:
2秒後...
delay:1
delay:2
delay:3複製程式碼
Repeat
repeat(long count)操作符,將Observable重複發射count次。
//重複發射5次“Sherlock”
Observable.just("Sherlock").repeat(5)
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("rx_test", "repeat:" + s);
}
});複製程式碼
輸出結果:
repeat:Sherlock
repeat:Sherlock
repeat:Sherlock
repeat:Sherlock
repeat:Sherlock複製程式碼
以上就是常用的一些建立操作符,類似但不常用的還有empty、never、error等等就不一一介紹了,有興趣的碼友可以自行百度。
執行緒排程Scheduler
RxJava就是用來處理非同步任務的,所以就牽扯到生產事件所線上程,處理事件所線上程的問題,下面來看一下RxJava提供的執行緒排程Scheduler都有哪些。
有了Scheduler,RxJava當然也提供了方法來使用它們。
.subscribeOn()指定被觀察者Observable的執行執行緒。
.observeOn()指定觀察者Observer的執行執行緒。
如第一篇文章中的例子:
//獲取要查詢的小區集合
Observable.from(getCommunitiesFromServer())
.flatMap(new Func1<Community, Observable<House>>() {
@Override
public Observable<House> call(Community community) {
return Observable.from(community.getHouses());
}
})
.filter(new Func1<House, Boolean>() {
@Override
public Boolean call(House house) {
return house.getPrice() < 200;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<House>() {
@Override
public void call(House house) {
//顯示查詢出來的房源資訊
ShowSearchedHousesMessage();
}
});複製程式碼
其中.subscribeOn(Schedulers.io())
指定了Observable在io執行緒執行,通常用來執行從伺服器獲取資料,資料庫載入等耗時操作。.observeOn(AndroidSchedulers.mainThread())
指定了Observer在Android環境下的UI執行緒執行,通常用來獲取到資料後進行UI重新整理的操作。可根據實際需求選擇不同執行緒型別。
總結
到此,本篇關於RxJava的建立類操作符以及執行緒排程就講解完畢了,下一篇我們將一起研究RxJava的四類操作符中的轉換操作符都有哪些以及如何使用。
技術渣一枚,有寫的不對的地方歡迎大神們留言指正,有什麼疑惑或者建議也可以在我Github上RxJavaDemo專案Issues中提出,我會及時回覆。
附上RxJavaDemo的地址:
RxJavaDemo