RxJava
提到Rxjava最多人都是用來處理,線程調度,回調地獄,加上Retrofit又支持Rxjava,所以大部分開發者都只會在請求網絡和需要切換線程的時候用到Rxjava,其實它有一個最重要的特性,它可以讓數據的流向更加直觀,代碼更清晰。
舉個栗子
比如說一個龐大的項目,一個事件傳遞的整個過程可能要經歷很多方法,方法套方法,每個方法的位置七零八落,一個個方法跳進去看,跳過去跳過來很容易把腦袋弄暈,不夠直觀。但是Rxjava可以把所有邏輯用鏈式加閉包的方式呈現,做了哪些操作,誰在前誰在后非常直觀,邏輯清晰,維護就會非常輕松。就算不是你寫的你也可以很快的了解,你可以把它看作一條河流,整個過程就是對里面的水流做進行加工。懂了這個特性我們才知道在復雜的邏輯中運用Rxjava是多么的重要。
Gradle添加依賴
要在Android中使用RxJava2, 先添加Gradle配置。
compile "io.reactivex.rxjava2:rxjava:2.0.7"
compile "io.reactivex.rxjava2:rxandroid:2.0.1"
一個簡單實例(分別創建被觀察者,觀察者和兩種對象進行關聯)
//創建被觀察者
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
//調用觀察者的回調
emitter.onNext("我是");
emitter.onNext("RxJava");
emitter.onNext("簡單示例");
emitter.onError(new Throwable("出錯了"));
emitter.onComplete();
}
});
//創建觀察者
Observer<String> observer = new Observer<String>() {
@Override
public void onError(Throwable e) {
Log.e(TAG,e.getMessage());
}
@Override
public void onComplete() {
Log.e(TAG,"onCompleted");
}
//onSubscribe()方法是最先調用的
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG,"subscribe");
}
@Override
public void onNext(String s) {
Log.d(TAG,s);
}
};
//注冊,將觀察者和被觀察者關聯,將會觸發OnSubscribe.call方法
observable.subscribe(observer);
運行結果:
Observable是被觀察者,創建后傳入一個OnSubscribe對象,當Observable(觀察者)調用subscribe進行注冊觀察者時,OnSubscribe的call方法會觸發。
ObservableEmitter: Emitter 是發射器的意思,它可以發出三種類型的事件,與之對應的。
Observer有三個回調方法:
- onNext:接受到一個事件
- onCompleted:接受完事件后調用,只會調用一次
- onError :發生錯誤時調用,并停止接受事件,調用一次
注:onCompleted和onError不會同時調用,只會調用其中之一
另一個簡單實例(訪問網絡時,通過RxJava來進行快捷的主線程和子線程切換)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView tv_return = (TextView) findViewById(R.id.tv_return);
//創建被觀察者
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
emitter.onNext(getResponse());
}
});
//創建觀察者
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String mResponse) throws Exception {
Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
tv_return.setText(mResponse);
}
};
//subscribeOn() 指定的是發送事件的線程, observeOn() 指定的是接收事件的線程.
observable.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(consumer);
}
//使用okhttp訪問網上提供的接口,由于是同步get請求,需要在子線程進行
private String getResponse() {
String url = "http://v.juhe.cn/weather/index?cityname=%E6%9D%AD%E5%B7%9E&dtype=&format=&key=7970495dbf33839562c9d496156e13cc";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
Response response;
try {
response = client.newCall(request).execute();
return response.body().string();
} catch (IOException e) {
return "error";
}
}
在RxJava中, 已經內置了很多線程選項供我們選擇, 例如有
- Schedulers.io() 代表io操作的線程, 通常用于網絡,讀寫文件等io密集型的操作
- Schedulers.computation() 代表CPU計算密集型的操作, 例如需要大量計算的操作
- Schedulers.newThread() 代表一個常規的新線程
- AndroidSchedulers.mainThread() 代表Android的主線程
這些內置的Scheduler已經足夠滿足我們開發的需求, 因此我們應該使用內置的這些選項,在RxJava內部使用的是線程池來維護這些線程,所有效率也比較高。
第三個簡單實例(類型變換操作)
RxJava提供了類型變換操作,像上面的發送網絡請求事件,得到網絡請求數據,傳遞和接收的都是字符串。
而RxJava中的map操作符可以對事件進行處理,比如發送網絡請求事件,通過map處理后,可以接收到網絡請求的字符串的字節數,如下所示。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView tv_return = (TextView) findViewById(R.id.tv_return);
//創建被觀察者
Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
emitter.onNext(getResponse());
}
//通過map操作符對數據進行中間處理
}).map(new Function<String, Integer>() {
@Override
public Integer apply(@NonNull String response) throws Exception {
return response.length();
}
});
//創建觀察者
Consumer<Integer> consumer = new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
tv_return.setText("字數:"+integer);
}
};
//綁定,指定線程
observable.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(consumer);
}
第四個簡單實例(鏈式操作)
而RxJava一個引以為豪的地方就是它的鏈式操作了,可以把被觀察者和觀察者串起來。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView tv_return = (TextView) findViewById(R.id.tv_return);
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
emitter.onNext(getResponse());
}
}).map(new Function<String, Integer>() {
@Override
public Integer apply(@NonNull String response) throws Exception {
return response.length();
}
}).subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer) throws Exception {
Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
tv_return.setText("字數:" + integer);
}
});
}
這里是項目地址 其實也沒啥東西
喜歡的同學可以點個贊
參考
https://xiaobailong24.me/2017/03/18/Android-RxJava2.x/
http://www.lxweimin.com/p/6fd8640046f1