RxJava 執行緒切換
RxJava中的執行緒切換
一般來說我們在使用網路請求資料後需要使用View來顯示,網路請求當然是在子執行緒中執行,當獲取到資料後就需要切換到UI執行緒來顯示,否則會報錯,RxJava中已經幫我們處理好了執行緒切換的問題。
Observable類兩個介面
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> subscribeOn(Scheduler scheduler) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null" );
return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> observeOn(Scheduler scheduler) {
return observeOn(scheduler, false, bufferSize());
}
上面兩個介面是用來做什麼用的呢?
Observable<T> subscribeOn(Scheduler scheduler)
註釋直接翻譯:在指定的Scheduler上非同步訂閱Observers到此ObservableSource
聽起來不太好理解,應該這樣說:在指定的排程執行緒上給可觀察源非同步的訂閱觀察者
Observable<T> observeOn(Scheduler scheduler)
註釋直接翻譯:修改ObservableSource以在指定的Scheduler上執行其發射和通知
也不太好理解,可以這樣說:修改被觀察源到指定的排程執行緒上去執行發射或通知(也就是說在另一個執行緒上去執行某些方法)
看了上面解釋可能還是一頭霧水,現在結合世界場景來理解,看下面示例程式碼
請求介面定義
public interface NetService {
@GET("?app=weather.future&weaid=1&&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json")
Observable<WeatherBeans> requestWeatherBeansRX();
}
介面使用
private void doGetWithRx() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://api.k780.com")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
NetService netService = retrofit.create(NetService.class);
Observable<WeatherBeans> observable = netService.requestWeatherBeansRX();
observable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<WeatherBeans>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe run");
}
@Override
public void onNext(WeatherBeans beans) {
StringBuilder sb = new StringBuilder();
if (beans != null) {
for (WeatherBeans.ResultBean bean : beans.getResult()) {
Log.d(TAG, "cityName:" + bean.getCitynm());
sb.append(bean.getCitynm()).append("、");
}
resultView.setText(sb.toString());
} else {
Log.d(TAG, "OnNext beans is null");
}
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "OnError run");
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete run");
}
});
}
從上面的示例程式碼我們看到在網路請求的鏈式呼叫。
observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())...
先看subscribeOn(Schedulers.io())
Schedulers.io()的註釋是:建立並返回用於IO繫結工作的Scheduler
那麼subscribeOn也就是在io執行執行緒訂閱,也就是說網路請求io操作在io執行緒
再看observeOn(AndroidSchedulers.mainThread())
AndroidSchedulers.mainThread():一個Scheduler,它在Android主執行緒上執行操作
這兩個介面的作用是如下:
subscribeOn(Schedulers.io())是指定observable的subscribeOn() 方法在後臺執行緒執行。
observeOn(AndroidSchedulers.mainThread())是指定 observer 的回撥方法在主執行緒執行。
實驗1
註釋subscribeOn(Schedulers.io())
結果輸出:
09-27 14:48:51.520 2879-2879/hq.demo.net D/NewOkHttpFragment: onSubscribe run 09-27 14:48:51.556 2879-2879/hq.demo.net D/NewOkHttpFragment: onError run
可以看到回調了onError,說明請求錯誤了
實驗2
註釋掉observeOn(AndroidSchedulers.mainThread())
結果輸出:
09-27 14:54:49.481 4059-4059/hq.demo.net D/NewOkHttpFragment: onSubscribe run 09-27 14:54:49.735 4059-4099/hq.demo.net D/NewOkHttpFragment: cityName:北京 09-27 14:54:49.735 4059-4099/hq.demo.net D/NewOkHttpFragment: cityName:北京 09-27 14:54:49.736 4059-4099/hq.demo.net D/NewOkHttpFragment: cityName:北京 09-27 14:54:49.736 4059-4099/hq.demo.net D/NewOkHttpFragment: cityName:北京 09-27 14:54:49.736 4059-4099/hq.demo.net D/NewOkHttpFragment: cityName:北京 09-27 14:54:49.736 4059-4099/hq.demo.net D/NewOkHttpFragment: cityName:北京 09-27 14:54:49.736 4059-4099/hq.demo.net D/NewOkHttpFragment: cityName:北京 09-27 14:54:49.738 4059-4099/hq.demo.net D/NewOkHttpFragment: OnError run
上面結果說明網路請求結果成功,但是resultView.setText(sb.toString());出錯,
實驗3
去掉所有註釋
結果輸出:
09-27 14:58:51.008 4349-4349/hq.demo.net D/NewOkHttpFragment: onSubscribe run 09-27 14:58:51.230 4349-4349/hq.demo.net D/NewOkHttpFragment: cityName:北京 09-27 14:58:51.230 4349-4349/hq.demo.net D/NewOkHttpFragment: cityName:北京 09-27 14:58:51.230 4349-4349/hq.demo.net D/NewOkHttpFragment: cityName:北京 09-27 14:58:51.230 4349-4349/hq.demo.net D/NewOkHttpFragment: cityName:北京 09-27 14:58:51.230 4349-4349/hq.demo.net D/NewOkHttpFragment: cityName:北京 09-27 14:58:51.230 4349-4349/hq.demo.net D/NewOkHttpFragment: cityName:北京 09-27 14:58:51.230 4349-4349/hq.demo.net D/NewOkHttpFragment: cityName:北京 09-27 14:58:51.232 4349-4349/hq.demo.net D/NewOkHttpFragment: onComplete run
總結:
RxJava在資料請求展示中的執行緒切換是通過下面介面處理的,
1、subscribeOn(Schedulers.io()) 指定observable的 subscribeOn() 方法在後臺執行緒執行。
2、observeOn(AndroidSchedulers.mainThread()) 指定 observer 的回撥方法在主執行緒執行。