RxJava接觸挺久了,但是在實際項目中大部分都是配合retrofit使網絡請求使用,其他需求比較少,就是想用的時候會忘記怎麼使用,所以這裏做個筆記,希望也能幫到他人
本文基於RxJava2.0
RxJava
自己覺得知道下面幾點就比較清楚了
- RxJava的異步實現,是通過一種擴展的觀察者模式來實現的
- RxJava 的觀察者模式:Observable (可觀察者,即被觀察者)、 Observer (觀察者)、 subscribe (訂閱)、事件。
- Observable 和 Observer 通過 subscribe() 方法實現訂閱關係,從而 Observable可以在需要的時候發出事件來通知 Observer
那麼既然是觀察者模式,那我們看下怎麼使用
創建被觀察者:使用基本的創建方式create()
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
//通知觀察者
e.onNext("通知觀察者");
e.onComplete();
}
});
創建觀察者
Observer observer = new Observer<String>() {
//RxJava 2.0 中新增的,傳遞參數爲Disposable ,Disposable 相當於RxJava1.x中的Subscription,用於解除訂閱。
@Override
public void onSubscribe(Disposable d) {
//可用於取消訂閱
d.dispose();
//還可以判斷是否處於取消狀態
//boolean b=d.isDisposed();
}
//觀察者接收到通知,進行相關操作
@Override
public void onNext(String o) {
Log.d("","接收到觀察者發出的數據");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
};
訂閱,將被觀察者和觀察者關聯上
observable.subscribe(observer);
其他創建被觀察者的方式
just(T…): 將傳入的參數依次發送出去
Observable observable = Observable.just("Hello", "Hi", "Aloha");
// 將會依次調用:
// onNext("Hello");
// onNext("Hi");
// onNext("Aloha");
// onCompleted();
Observable.from… 拆分成具體對象後,依次發送出去
String[] words = {"Hello", "Hi", "Aloha"};
Observable observable = Observable.from(words);
// 將會依次調用:
// onNext("Hello");
// onNext("Hi");
// onNext("Aloha");
// onCompleted();
線程的切換–線程控制器的使用(Schedulers)
看下面的code 想大家看下注釋就會明白了
Observable.just("a", "b", "c", "d")
.subscribeOn(Schedulers.io())//指定數據發射在哪個線程執行
.observeOn(Schedulers.newThread())//observeOn方法決定他下面的方法執行在哪個線程中
.map(func1)//一個新線程中執行
.observeOn(Schedulers.io())//observeOn方法決定他下面的方法執行在哪個線程中
.map(func2)//io線程執行
.observeOn(AndroidSchedulers.mainThread())////observeOn方法決定他下面的方法執行在哪個線程中
.subscribe(consumer);//ui線程執行
Function<String, String> func1 = new Function<String, String>() {
@Override
public String apply(String s) throws Exception {
return s + "===newThread===";
}
};
Function<String, String> func2 = new Function<String, String>() {
@Override
public String apply(String s) throws Exception {
return s + "===io===";
}
};
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String o) throws Exception {
Log.d("call", o.toString());
}
};
下面我們根據場景來進行使用
- 場景一: 單請求異步處理(網絡請求)
- 場景二: 多異步請求連續調用
- 場景三: 進行數組、list的遍歷(耗時數據處理)
- 場景四: 多異步請求合併處理
場景五: 定時操作
示例中會伴有Rxjava 的操作符出現,使用時會進行說明
場景一: 單請求異步處理(網絡請求)
由於在Android UI線程中不能做一些耗時操作,比如網絡請求,大文件保存等,所以在開發中經常會碰到異步處理的情況,我們最典型的使用場景是RxJava+Retrofit處理網絡請求
@GET("/user")
public Observable<User> getUser(@Query("userId") String userId);
getUser(userId)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<User>() {
@Override
public void onNext(User user) {
userView.setUser(user);//使用得到的結果數據
}
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable error) {
// Error handling
...
}
});
場景er: 多異步請求連續調用
假如在得到User數據後,需要跟新本地的用戶數據,也是將新的額數據顯示到View上,兩步操作都是同時的,這個時候我們可以藉助”doOnNext “操作符
“doOnNext “操作符
doOnNext() 方法 是當onNext發生時纔會被調用
doOnNext()允許我們在每次輸出一個元素之前做一些額外的事情
注意:
在doOnNext()中不要去改變數據的值
processUser(user); // 嘗試修正 User 數據
userView.setUser(user);//顯示數據
代碼
getUser(userId)
.doOnNext(new Consumer<User>() {
@Override
public void accept(User user) throws Exception {
processUser(user);//更改數據
}
})
.observeOn(AndroidSchedulers.mainThread())//ui線程
.subscribe(new Observer<User>() {
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(User user) {
userView.setUser(user);//展示數據
}
});
如果請求getUser()之前需要getToken接口返回的數據才能訪問
使用”flatmap”操作符
作用:將一個類型依據程序邏輯轉換成另一種類型
@GET("/token")
public Observable<String> getToken();
@GET("/user")
public Observable<User> getUser(@Query("token") String token, @Query("userId") String userId);
getToken()
.flatMap(new Function<String, Observable<User>>() {
@Override
public Observable<User>> apply(String token) throws Exception {
return getUser(token, userId);//第二次網絡請求
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<User>() {
@Override
public void onSubscribe(Disposable disposable) {
}
@Override
public void onNext(User user) {
//獲取到的用戶數據
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onComplete() {
}
});
場景三: 進行數組、list的遍歷(耗時數據處理)
使用”fromIterable”操作符 ,作用:遍歷發送列表的每個Item
ArrayList<String> arr1 = new ArrayList<>();
arr1.add("url1");
arr1.add("url2");
arr1.add("url3");
Observable.just(arr1)
.subscribeOn(Schedulers.newThread())//指定數據發射在哪個線程執行
.flatMap(new Function<List<String>, Observable<String>>() {
@Override
public Observable<String> apply(List<String> strings) throws Exception {
Log.d("flatMap Thread ::: ", Thread.currentThread().getName());
return Observable.fromIterable(strings);//遍歷列表發送
}
})
.observeOn(AndroidSchedulers.mainThread())//切換到主線程
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d("subscribe Thread ::: ", Thread.currentThread().getName());
Log.d("subscribe === ", s);
}
});
場景四: 多異步請求合併處理
有時需要請求多個接口和,將多個接口請求回來的數據合併後使用,可以使用”zip”操作符
作用:組合多個Observable發射的數據集合,然後再發射這個組合結果Observable
Observable.zip(getData1(), getData2(), new BiFunction<List<String>, List<String>, String>() {
@Override
public String apply(List<String> strings, List<String> strings2) throws Exception {
return strings.get(0) + strings.get(0);//發送組合後的新數據
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d("接受新數據:::", s);
}
});
/**
* 模擬請求數據1
*
* @return
*/
private Observable<List<String>> getData1() {
return Observable.create(new ObservableOnSubscribe<List<String>>() {
@Override
public void subscribe(ObservableEmitter<List<String>> e) throws Exception {
ArrayList<String> contacters = new ArrayList<>();
contacters.add("location:張三");
contacters.add("location:李四");
contacters.add("location:王五");
e.onNext(contacters);
e.onComplete();
}
});
}
/**
* 模擬獲取數據2
*
* @return
*/
private Observable<List<String>> getData2() {
return Observable.create(new ObservableOnSubscribe<List<String>>() {
@Override
public void subscribe(ObservableEmitter<List<String>> e) throws Exception {
ArrayList<String> contacters = new ArrayList<>();
contacters.add("net:Zeus");
contacters.add("net:Athena");
contacters.add("net:Prometheus");
e.onNext(contacters);
e.onComplete();
}
});
}
場景五: 定時操作
使用timer做定時操作。當有“x秒後執行y操作”類似的需求的時候,想到使用timer
* 例如:2秒後輸出日誌“hello world”,然後結束。
//2秒後執行
Observable.timer(2, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())//切換到主線程
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
tv_msg.setText("hello --- world");
}
});
更多操作符使用,後續有時間再記錄