之前沒有了解過Rxjava的童鞋铣卡,建議先閱讀《Rxjava 從入門到開發(fā)》這篇文章伸但,對入門比較有幫助眯牧。
map操作符
作用:通過call函數(shù)根據(jù)函數(shù)Func1<T,K>把T轉(zhuǎn)換為K
List<Student> students=new ArrayList<>();
Student stuent=new Student();
stuent.setName("小一");
Student s1=new Student();
s1.setName("小二");
students.add(stuent);
students.add(s1);
subscription=Observable.from(students).map(new Func1<Student, String>() {
@Override
public String call(Student student) {
return student.getName();
}
}).subscribe(new Action1<String>() {
@Override
public void call(String s) {
Logger.i("MapOperation : "+s);
}
});
輸出結(jié)果:
例子說明:通過map操作符糠睡,我們把輸入的Student對象轉(zhuǎn)換成了String變量脏毯,然后遍歷輸出。
flag map操作符
作用:對序列的每一項(xiàng)通過call函數(shù)根據(jù)函數(shù)Func1<T,Observable<K>>把T通過操作符轉(zhuǎn)換為K
Observable.just(10, 20, 30).flatMap(new Func1<Integer, Observable<Integer>>() {
@Override
public Observable<Integer> call(Integer integer) {
//10的延遲執(zhí)行時(shí)間為200毫秒霜瘪、20和30的延遲執(zhí)行時(shí)間為180毫秒
int delay = 200;
if (integer > 10)
delay = 180;
return Observable.from(new Integer[]{integer, integer / 2}).delay(delay, TimeUnit.MILLISECONDS);
}
}).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
System.out.println("flatMap Next:" + integer);
}
});
輸出結(jié)果:
例子說明:輸入數(shù)字10珠插,20,30通過操作符from和delay輸出颖对,這里要注意的是捻撑,輸出結(jié)果已經(jīng)出現(xiàn)了亂序,即沒有按照10缤底,5顾患;20,10个唧;30江解,15的順序輸出。
concatMap操作符
作用:對序列的每一項(xiàng)通過call函數(shù)根據(jù)函數(shù)Func1<T,Observable<K>>把T通過操作符轉(zhuǎn)換為K徙歼,相對于flatmap可以保證輸出順序一致
Observable.just(10, 20, 30).concatMap(new Func1<Integer, Observable<Integer>>() {
@Override
public Observable<Integer> call(Integer integer) {
//10的延遲執(zhí)行時(shí)間為200毫秒犁河、20和30的延遲執(zhí)行時(shí)間為180毫秒
int delay = 200;
if (integer > 10)
delay = 180;
return Observable.from(new Integer[]{integer, integer / 2}).delay(delay, TimeUnit.MILLISECONDS);
}
}).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
System.out.println("concatMap Next:" + integer);
}
});
輸出結(jié)果:
例子說明:輸入數(shù)字10鳖枕,20,30通過操作符from和delay輸出桨螺,這里要注意的是耕魄,輸出結(jié)果沒有出現(xiàn)亂序
switchMap操作符
作用:對序列的每一項(xiàng)通過call函數(shù)根據(jù)函數(shù)Func1<T,Observable<K>>把T通過操作符轉(zhuǎn)換為K,若結(jié)果k1,k2同時(shí)出現(xiàn)則則會(huì)保留最新的k2彭谁,丟棄k1
Observable.just(10, 20, 30).switchMap(new Func1<Integer, Observable<Integer>>() {
@Override
public Observable<Integer> call(Integer integer) {
//10的延遲執(zhí)行時(shí)間為200毫秒吸奴、20和30的延遲執(zhí)行時(shí)間為180毫秒
int delay = 200;
if (integer > 10)
delay = 180;
return Observable.from(new Integer[]{integer, integer / 2}).delay(delay, TimeUnit.MILLISECONDS);
}
}).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
System.out.println("switchMap Next:" + integer);
}
});
輸出結(jié)果:
例子說明:輸入數(shù)字10,20缠局,30通過操作符from和delay輸出则奥,但是由于switchmap操作符的作用,10的輸出被20覆蓋狭园,20的輸出結(jié)果被30覆蓋读处,故最后只有30,15輸出唱矛。
以上demo 出自Android RxJava使用介紹(三) RxJava的操作符罚舱,最后總結(jié)下map,flatmap绎谦,contactmap管闷,switchmap的使用場景區(qū)別:map用于不需要通過操作符就可以完成的轉(zhuǎn)換,flatmap用于需要通過操作符才可以轉(zhuǎn)換的操作窃肠,但是輸出結(jié)果可能會(huì)是亂序包个,contactmap的作用在flatmap的基礎(chǔ)上保證輸出結(jié)果按照輸入順序輸出,switchmap的作用在flatmap的基礎(chǔ)上冤留,對輸出結(jié)果若同時(shí)發(fā)生碧囊,只會(huì)保證最新結(jié)果而放棄舊數(shù)據(jù)。
Scan操作符
作用:連續(xù)地對數(shù)據(jù)序列的每一項(xiàng)應(yīng)用一個(gè)函數(shù)纤怒,然后連續(xù)發(fā)射結(jié)果
Integer numbers[]={1,2,3,4,5,};
Observable observable=Observable.from(numbers);
subscription=observable.scan(new Func2<Integer,Integer,Integer>() {
@Override
public Integer call(Integer sum, Integer item) {
System.out.println(" sum: "+sum+" item: "+item);
return sum+item;
}
})
.subscribe(new Action1() {
@Override
public void call(Object o) {
System.out.println(" number: "+o);
}
});
SubscriptionManager.setSubscription(subscription);
輸出結(jié)果:
例子說明:這里要注意的是變量sum等于輸入數(shù)相加糯而,item為某項(xiàng)輸入,例如:現(xiàn)在輸入的是3泊窘,即item為3熄驼,sum則為1和2相加的結(jié)果,最后返回的是3+3等6州既,下一步輸入item為4谜洽,則sum為6萝映,接下來返回的便是6+4的結(jié)果吴叶。
groupBy操作符
作用:可以對輸入的數(shù)據(jù)根據(jù)自定義類型分組
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
for(int i=0;i<6;i++){
int number=random.nextInt(10);
System.out.println("key: " + number);
subscriber.onNext(number);
}
}
}).groupBy(new Func1<Integer, String>() {
@Override
public String call(Integer value) {
return value % 2 == 0 ? "偶數(shù)" : "奇數(shù)";
}
}).subscribe(new Action1<GroupedObservable<String, Integer>>() {
@Override
public void call(final GroupedObservable<String, Integer> stringIntegerGroupedObservable) {
stringIntegerGroupedObservable.subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
System.out.println("key:" + stringIntegerGroupedObservable.getKey() +", value:" + integer);
}
});
}
});
輸出結(jié)果:
例子說明:輸入六個(gè)隨機(jī)數(shù)8,1序臂,2蚌卤,8实束,7,8逊彭,結(jié)果我原以為數(shù)據(jù)會(huì)先輸出偶數(shù)項(xiàng)咸灿,再輸出奇數(shù)項(xiàng),但是結(jié)果卻是輸出數(shù)據(jù)的順序和輸入一致侮叮,但是通過GroupedObservable.getkey 方法可以獲取數(shù)據(jù)所屬分類避矢。另外這里需要注意的是:groupBy將原始Observable分解為一個(gè)發(fā)射多個(gè)GroupedObservable的Observable,一旦有訂閱囊榜,每個(gè)GroupedObservable就開始緩存數(shù)據(jù)审胸。因此,如果你忽略這些GroupedObservable中的任何一個(gè)卸勺,這個(gè)緩存可能形成一個(gè)潛在的內(nèi)存泄露砂沛。因此,如果你不想觀察曙求,也不要忽略GroupedObservable碍庵。你應(yīng)該使用像take(0)這樣會(huì)丟棄自己的緩存的操作符。
Buffer操作符
作用:定期收集Observable的數(shù)據(jù)放進(jìn)一個(gè)數(shù)據(jù)包裹悟狱,然后發(fā)射這些數(shù)據(jù)包裹静浴,而不是一次發(fā)射一個(gè)值。
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
final String[] names = {"小-", "小二", "小三", "小四", "小五"};
Random random = new Random();
if(subscriber.isUnsubscribed()){
return;
}
do {
String name = names[random.nextInt(names.length)];
subscriber.onNext(name);
try {
Thread.sleep(1000);
}catch (Exception e){
e.printStackTrace();
}
} while (true);
}
}).subscribeOn(Schedulers.io()).buffer(2,TimeUnit.SECONDS).subscribe(new Action1<List<String>>() {
@Override
public void call(List<String> strings) {
System.out.println("開始兩秒點(diǎn)一次名字...");
for (String name:strings) {
System.out.println("name: "+name);
}
}
});
輸出結(jié)果:
例子說明:create操作符里面一直在做每隔1秒就發(fā)送一個(gè)隨機(jī)名字的操作挤渐,通過buffer操作符可以實(shí)現(xiàn)每隔2秒輸出一組名字马绝。
Window操作符
作用:和buffer類似作用類似,但是輸出的是Observable而不是具體數(shù)據(jù)
Observable.interval(1, TimeUnit.SECONDS).take(10).
window(2,TimeUnit.SECONDS).subscribe(new Action1<Observable<Long>>() {
@Override
public void call(Observable<Long> longObservable) {
System.out.println("每隔兩秒打印.....");
longObservable.subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
System.out.println("currentNumber: "+aLong);
}
});
}
});
輸出結(jié)果:
例子說明:interval操作符表示按照順序和預(yù)期時(shí)間輸出一個(gè)0-n的數(shù)列挣菲,例如:0富稻,1,2...n, take操作符表示截取前n個(gè)結(jié)果集白胀,在例子中就是截取interval操作符輸出的0-9共10個(gè)數(shù)椭赋,** window操作符作用和buffer差不多,不同的是buffer輸出具體的數(shù)值或杠,但是Window輸出的Observable哪怔,需要再進(jìn)一步訂閱才能輸出具體數(shù)值**。
Cast操作符
作用:對數(shù)據(jù)進(jìn)行強(qiáng)轉(zhuǎn)類型
但是實(shí)際使用中本人發(fā)現(xiàn)僅僅能用于對輸入數(shù)據(jù)的類型判斷是否符合預(yù)期
String[] strs=new String[]{"1","2","3","4","5"};
subscription=Observable.from(strs).observeOn(Schedulers.io()).cast(Integer.class).subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
System.out.println("integer: " + integer);
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
throwable.printStackTrace();
}
});
輸出結(jié)果:
例子說明:輸入類型正確則輸出源數(shù)據(jù)向抢,如果輸入數(shù)據(jù)某項(xiàng)內(nèi)容類型不正確认境,則報(bào)錯(cuò)。
以上便是變換操作符的主要內(nèi)容了挟鸠。有啥問題歡迎大家留言交流下??叉信,下篇文章再說說過濾操作符歡迎關(guān)注。
附錄:
文章demo