RxJava是什麼
RxJava是一種異步方式:類似於android中的AsyncTask 和Handler ,RxJava並不是一個”拿來就能用”的項目,他需要我們像學習門新語言一樣從語法–>詞彙–>用法的學習過程
作用是什麼
用於:邏輯的簡潔,並不是單純的代碼量少
RxJava 的使用
- 創建一個被觀察者
Observable<String> myObservable = Observable.create(
new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> sub) {
sub.onNext("Hello, world!");
sub.onCompleted(); //標記完成
}
}
);
2.創建一個Subscriber來處理Observable對象發出的字符串
Subscriber<String> mySubscriber = new Subscriber<String>() {
@Override
public void onNext(String s) { System.out.println(s); }
@Override
public void onCompleted() { }
@Override
public void onError(Throwable e) { }
};
3.通過subscribe函數就可以將我們定義的myObservable對象和mySubscriber對象關聯起來,這樣就完成了subscriber對observable的訂閱。
myObservable.subscribe(mySubscriber);//訂閱
以上代碼簡化
RxJava 提供了很多簡化創建Observable對象的方法
如:Observable.just(),用來創建只發出一個事件就結束的Observable對象
//創建Observable 簡化代碼
Observable<String> myObservable = Observable.just("Hello, world!");
//簡化Subscriber,在Subscriber中我們關注的只有onNext 一個方法,這時候就可以使用Action1 類
Action1<String> onNextAction = new Action1<String>(){
@Override
public void call(String s) {
Log.e("onCompleted", s);
}
};
//訂閱 subscribe方法有一個重載版本,接受三個Action1類型的參數,分別對應OnNext,OnComplete, OnError函數。
//這裏我們並不關心onError和onComplete,所以只需要第一個參數就可以
myObservable.subscribe(onNextAction);
再簡化
Observable.just("Hello, world!")
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("call", s);
}
});
錯誤處理
onComplete()和onError()函數。這兩個函數用來通知訂閱者,被觀察的對象將停止發送數據以及爲什麼停止(成功的完成或者出錯了)
RxJava 中的操作符
1. 操作符(map)
作用:操作符用於在Observable和最終的Subscriber之間修改Observable發出的事件,就是用來把把一個事件轉換爲另一個事件的
案例:在hello world中加上我的簽名,會想到要去修改被觀察者,如果加上簽名這個需求只針對於某個訂閱者,那麼去修改被觀察者顯然不行,這個時候就用到了map操作符,變換Observable對象
Observable.just("Hello, world!")
.map(new Func1<String, String>() {
@Override
public String call(String s) {
return s + " RxJava";
}
})
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("call", s);
}
});
改變數據類型的observable對象
Observable.just("Hello, world!")
.map(new Func1<String, Integer>() {
@Override
public Integer call(String s) {
return s.hashCode();
}
})
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
Log.e("call", integer.toString());
}
});
這裏出現了一個叫做 Func1 的類。它和 Action1 非常相似,也是 RxJava 的一個接口,用於包裝含有一個參數的方法。 另外,和 ActionX 一樣, FuncX 也有多個,用於不同參數個數的方法。FuncX 和 ActionX 的區別在 FuncX 包裝的是有返回值的方法。
Observable和Subscriber可以做任何事情
Observable可以是一個數據庫查詢,Subscriber用來顯示查詢結果;Observable可以是屏幕上的點擊事件,Subscriber用來響應點擊事件;Observable可以是一個網絡請求,Subscriber用來顯示請求結果。Observable和Subscriber是獨立於中間的變換過程的。
在Observable和Subscriber中間可以增減任何數量的map。整個系統是高度可組合的,操作數據是一個很簡單的過程。
2.操作符from
操作數組或者集合中每個數據,不需要使用for 來遍歷
Observable.from()方法,它接收一個集合作爲輸入,然後每次輸出一個元素給subscriber:
案例:根據輸入的字符串返回一個網站的url列表(搜索引擎)
query("Hello, world!")
.subscribe(new Action1<List<String>>() {
@Override
public void call(List<String> strings) {
for(String s:strings){
Log.e("call", s);
}
}
});
使用from操作符
query("Hello, world!")
.subscribe(new Action1<List<String>>() {
@Override
public void call(List<String> strings) {
// for(String s:strings){
// Log.e("call", s);
// }
Observable.from(strings)
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("call", s);
}
});
}
});
多個嵌套的subscription,進行修改
3.操作符(flatMap())
Observable.flatMap()接收一個Observable的輸出作爲輸入,同時輸出另外一個Observable
query("Hello, world!")
.flatMap(new Func1<List<String>, Observable<String>>() {
@Override
public Observable<String> call(List<String> strings) {
return Observable.from(strings);
}
})
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("call", s);
}
});
flatMap()可以返回任何它想返回的Observable對象。
4.操作符merge,合併觀察者對象
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<String> list2 = new ArrayList<String>();
list1.add("1");
list1.add("2");
list1.add("3");
list2.add("a");
list2.add("b");
list2.add("c");
Observable mObservable1 = Observable.from(list1);
Observable mObservable2 = Observable.from(list2);
//合併數據 先發送observable2的全部數據,然後發送 observable1的全部數據
Observable mObservable3 = Observable.merge(mObservable2, mObservable1);
mObservable3.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.d("call3",o.toString());
}
});
5. 操作符zip
zip 操作符,合併多個觀察對象的數據。並且允許 Func2()函數重新發送合併後的數據
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<String> list2 = new ArrayList<String>();
list1.add("1");
list1.add("2");
list1.add("3");
list2.add("a");
list2.add("b");
list2.add("c");
Observable mObservable1 = Observable.from(list1);
Observable mObservable2 = Observable.from(list2);
//合併Observable數據 ,並重新發送組合後的數據
Observable mObservable3 = Observable.zip(mObservable1, mObservable2, new Func2<String,String,String>() {
@Override
public String call(String s, String s2) {
return s+s2;
}
});
mObservable3.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.d("zip === ",o.toString());
}
});
6. scan累加器操作符的使用
Observable mObservable = Observable.just(1, 2, 3, 4, 5);
//返回相加結果
Observable mObservableScan = mObservable.scan(new Func2<Integer, Integer, Integer>() {
@Override
public Integer call(Integer o, Integer o2) {
return o + o2;
}
});
mObservableScan.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.d("scan == ", o.toString());
}
});
打印結果
D/scan ==: 1
D/scan ==: 3
D/scan ==: 6
D/scan ==: 10
D/scan ==: 15
7. filter 過濾操作符的使用
滿足結果纔會發送
Observable mObservable = Observable.just(1, 2, 3, 4, 5, 6, 7);
//過濾
Observable mObservableFilter = mObservable.filter(new Func1<Integer,Boolean>() {
@Override
public Boolean call(Integer o) {
//數據大於4的時候纔會被髮送
return o > 4;
}
});
mObservableFilter.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.d("filter == ", o.toString());
}
});
結果
D/filter ==: 5
D/filter ==: 6
D/filter ==: 7
8. 消息數量過濾操作符的使用
take :取前n個數據
takeLast:取後n個數據
first 只發送第一個數據
last 只發送最後一個數據
skip() 跳過前n個數據發送後面的數據
skipLast() 跳過最後n個數據,發送前面的數據
Observable mObservable = Observable.just(1, 2, 3, 4, 5, 6, 7);
//take 發送前三個數據
Observable mObservableTake = mObservable.take(3);
mObservableTake.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.d("take == ", o.toString());
}
});
//takeLast 發送後三個數據
Observable mObservableTakeLast = mObservable.takeLast(3);
mObservableTakeLast.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.d("takeLast",o.toString());
}
});
//first 只發送第一個數據
Observable mObservableFirst = mObservable.first();
mObservableFirst.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.d("first === ",o.toString());
}
});
//last 只發送最後一個數據
Observable mObservableLast = mObservable.last();
mObservableLast.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.d("last === ",o.toString());
}
});
//skip 跳過前2個數據發送後面的數據
Observable mObservableSkip = mObservable.skip(2);
mObservableSkip.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.d("skip === ",o.toString());
}
});
//skipLast 跳過最後2個數據發送後面的數據
Observable mObservableSkipLast = mObservable.skipLast(2);
mObservableSkipLast.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.d("skipLast === ",o.toString());
}
});
結果
D/take ==: 1
D/take ==: 2
D/take ==: 3
D/takeLast: 5
D/takeLast: 6
D/takeLast: 7
D/first ===: 1
D/last ===: 7
D/skip ===: 3
D/skip ===: 4
D/skip ===: 5
D/skip ===: 6
D/skip ===: 7
D/skipLast ===: 1
D/skipLast ===: 2
D/skipLast ===: 3
D/skipLast ===: 4
D/skipLast ===: 5
9. elementAt 、elementAtOrDefault
注意:elementAt() 發送數據序列中第n個數據 ,序列號從0開始,如果該序號大於數據序列中的最大序列號,則會拋出異常,程序崩潰,所以在用elementAt操作符的時候,要注意判斷髮送的數據序列號是否越界
Observable mObservable = Observable.just(1, 2, 3, 4, 5, 6, 7);
Observable mObservableElementAt = mObservable.elementAt(2);
mObservableElementAt.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.d("elementAt === ", o.toString());
}
});
// elementAtOrDefault( int n , Object default ) 發送數據序列中第n個數據 ,序列號從0開始。
// 如果序列中沒有該序列號,則發送默認值
Observable mObservableElementAtOrDefault = mObservable.elementAtOrDefault(8,0);
mObservableElementAtOrDefault.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.d("elementAtOrDefault === ",o.toString());
}
});
結果
D/elementAt ===: 3
D/elementAtOrDefault ===: 0
10.startWith() 插入數據
在已有數據之前插入數據,數據類型可以是普通類型和Observable 對象
Observable mObservable = Observable.just("aa","bb","cc");
Observable mObservableStartWith = mObservable.startWith("11", "22");
mObservableStartWith.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.d("StartWith 插入普通數據", o.toString());
}
});
//插入Observable對象
ArrayList<String> list = new ArrayList<String>();
list.add("ww");
list.add("tt");
mObservable.startWith(Observable.from(list))
.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.d("startWith 插入Observable 對象",o.toString());
}
});
結果
D/StartWith 插入普通數據: 11
D/StartWith 插入普通數據: 22
D/StartWith 插入普通數據: aa
D/StartWith 插入普通數據: bb
D/StartWith 插入普通數據: cc
D/startWith 插入Observable 對象: ww
D/startWith 插入Observable 對象: tt
D/startWith 插入Observable 對象: aa
D/startWith 插入Observable 對象: bb
D/startWith 插入Observable 對象: cc
11.delay操作符,延遲數據發送
只限制第一條數據發送的時間
Observable mObservable = Observable.just("aa","bb","cc");
//延遲數據發射的時間,僅僅延時一次,也就是發射第一個數據前延時。發射後面的數據不延時
Observable mObservableDelay = mObservable.delay(2, TimeUnit.SECONDS);//延遲兩秒發送
mObservableDelay.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.d("delay ==", o.toString());
}
});
12. interval 輪詢操作符,循環發送數據,數據從0開始遞增
private Subscription mSubscription;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//參數一:延遲時間 參數二:間隔時間 參數三:時間顆粒度 MILLISECONDS 每秒一次
Observable mObservable = Observable.interval(3000, 1000, TimeUnit.MILLISECONDS);
mSubscription= mObservable.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.d("interval == ", o.toString());
}
});
}
//銷燬的時候停止輪詢
@Override
protected void onDestroy() {
super.onDestroy();
if(mSubscription !=null){
mSubscription.unsubscribe();
}
}
結果
D/interval ==: 0
D/interval ==: 1
D/interval ==: 2
D/interval ==: 3
D/interval ==: 4
D/interval ==: 5
D/interval ==: 6
D/interval ==: 7
D/interval ==: 8
I/[Gralloc]: gralloc_unregister_buffer line 259 size3686400 base0x603ef000 phys_addr0 share_fd55 usage0x900 ion_hnd_debug0x2
I/[Gralloc]: gralloc_unregister_buffer line 259 size3686400 base0x614d4000 phys_addr0 share_fd60 usage0x900 ion_hnd_debug0x7
D/interval ==: 9
13.doOnNext() 操作符,在每次 OnNext() 方法被調用前執行
Observable mObservable = Observable.just("1", "2", "3", "4");
mObservable.doOnNext(new Action1() {
@Override
public void call(Object o) {
Log.d("doOnNext call",o.toString());
}
}).subscribe(new Observer() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Object o) {
Log.d("onNext",o.toString());
}
});
結果
D/doOnNext call: 1
D/onNext: 1
D/doOnNext call: 2
D/onNext: 2
D/doOnNext call: 3
D/onNext: 3
D/doOnNext call: 4
D/onNext: 4
14. throttleFirst 操作符
在一段時間內,只取第一個事件,然後其他事件都丟棄。
使用場景:1、button按鈕防抖操作,防連續點擊 2、百度關鍵詞聯想,在一段時間內只聯想一次,防止頻繁請求服務器
Subscription mSubscription;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//使用interval 達到每秒發送一個,在3秒內只取一個事件,其他的丟失
mSubscription = Observable.interval(1, TimeUnit.SECONDS)
.throttleFirst(3, TimeUnit.SECONDS)
.subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
Log.d("throttleFirst == ", aLong.toString());
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mSubscription != null) {
mSubscription.unsubscribe();
}
}
結果
D/throttleFirst ==: 0
D/throttleFirst ==: 4
D/throttleFirst ==: 7
D/throttleFirst ==: 10
D/throttleFirst ==: 13
D/throttleFirst ==: 16
D/throttleFirst ==: 19
D/throttleFirst ==: 22
D/throttleFirst ==: 25
15.distinct 過濾重複的數據
ArrayList<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
list.add("1");
list.add("3");
list.add("4");
list.add("2");
list.add("2");
list.add("1");
Observable.from(list)
.distinct()
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.d("distinct == ", s);
}
});
結果
D/distinct ==: 1
D/distinct ==: 2
D/distinct ==: 3
D/distinct ==: 4
16. distinctUntilChanged() 過濾連續重複的數據
ArrayList<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
list.add("1");
list.add("3");
list.add("4");
list.add("2");
list.add("2");
list.add("1");
Observable.from(list)
.distinct()
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.d("distinct == ", s);
}
});
Observable.from(list)
.distinctUntilChanged()//過濾連續重複的數據
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.d("distinctUntilChange == ", s);
}
});
結果
D/distinctUntilChanged ==: 1
D/distinctUntilChanged ==: 2
D/distinctUntilChanged ==: 1
D/distinctUntilChanged ==: 3
D/distinctUntilChanged ==: 4
D/distinctUntilChanged ==: 2
D/distinctUntilChanged ==: 1