学习小目标:
1、使用RxJava + Retrofit 进行网络请求数据,并在TextView中显示结果
2、掌握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 的回调方法在主线程运行。