异步多线程java
延迟触发react
循环定时触发android
项目开发中必定会用到网络请求,文件读写,开启子线程进行耗时操做,延迟返回或关闭提示框,轮询接口获取处理结果,子线程发送内容到主线程更新界面等等。碰到这些问题或需求的时候,每位程序猿都会使用本身喜欢或习惯的用法来实现或界面问题。固然结果是功能完成了或问题修复了。可是代码风格的差别,使用时考虑不全,使用方法不是最优,等等多多少少存在一些瑕疵。例如:git
api 'io.reactivex.rxjava2:rxandroid:2.1.0'
api 'io.reactivex.rxjava2:rxjava:2.2.5'
api 'com.squareup.retrofit2:retrofit:2.5.0'
api 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
api 'com.squareup.retrofit2:converter-gson:2.5.0'
复制代码
关于RxJava的方法介绍或基础使用,请参考RxJava2在Android中的使用。github
RxJava多线程 使用RxJava进行多线程操做的原理、用法及其余,请参考在 Andoid 中如何使用 RxJava 2 进行多线程编程?.编程
Scheduler 针对多线程的操做,Schedulers的参数了解,请参考我所理解的RxJava——上手其实很简单(三);api
最直接的用法就是new Thread()建立一个子线程,而后用EventMessage或Handler发送Message来更新页面。更好一点的方法是ExecutorService建立线程池,统一管理线程而且复用线程以及控制线程的总数,可是须要再花点时间维护和优化。可是不建议为每个Activity或fragment建立一个线程池,从性能和线程复用率上没有必要性。安全
private void testCreate() {
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
Log.e("wyn", "ObservableEmitter");
Log.e("wyn", "ObservableEmitter thread is " + Thread.currentThread().getName());
long a = 1;
for (int i = 0; i < 1000000000; i++) {
a = a + (a + 1);
}
Log.e("wyn", "a is " + a);
emitter.onNext("wang" + a);
emitter.onNext("yinan");
emitter.onComplete();
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this.observerString);
}
复制代码
打印的结果bash
2019-01-18 11:03:08.326 27120-27120/? E/wyn: onSubscribe
2019-01-18 11:03:08.326 27120-27120/? E/wyn: onSubscribe thread is main
2019-01-18 11:03:08.328 27120-27138/? E/wyn: ObservableEmitter
2019-01-18 11:03:08.328 27120-27138/? E/wyn: ObservableEmitter thread is RxCachedThreadScheduler-1
2019-01-18 11:03:13.226 27120-27138/com.example.RxThread E/wyn: a is -1
2019-01-18 11:03:13.227 27120-27120/com.example.RxThread D/wyn: onNext is wang-1
2019-01-18 11:03:13.227 27120-27120/com.example.RxThread E/wyn: onNext thread is main
2019-01-18 11:03:13.229 27120-27120/com.example.RxThread D/wyn: onNext is yinan
2019-01-18 11:03:13.229 27120-27120/com.example.RxThread E/wyn: onNext thread is main
2019-01-18 11:03:13.229 27120-27120/com.example.RxThread E/wyn: onComplete
2019-01-18 11:03:13.229 27120-27120/com.example.RxThread E/wyn: onComplete thread is main
复制代码
使用create方法简易的实现子线程操做(subscribeOn设置子线程类型),发送内容(onNext发送内容)到主线程(observeOn设置在主线程操做)更新界面。网络
最直接的方案就是postDelayed()触发一个延迟的操做。若是是在子线程进行postDelayed()操做,那么不能直接使用,会崩溃。
private void testTimer() {
Observable.timer(3, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this.observer);
}
复制代码
输出:
2019-01-18 11:31:11.820 28231-28231/com.example.RxThread E/wyn: onSubscribe
2019-01-18 11:31:11.820 28231-28231/com.example.RxThread E/wyn: onSubscribe thread is main
2019-01-18 11:31:14.832 28231-28231/com.example.RxThread D/wyn: onNext is 0
2019-01-18 11:31:14.833 28231-28231/com.example.RxThread E/wyn: onNext thread is main
2019-01-18 11:31:14.835 28231-28231/com.example.RxThread E/wyn: onComplete
2019-01-18 11:31:14.835 28231-28231/com.example.RxThread E/wyn: onComplete thread is main
复制代码
Timer能够在子线程进行延迟操做,那么输出结果为:
2019-01-18 11:33:14.018 28398-28419/? E/wyn: onSubscribe
2019-01-18 11:33:14.019 28398-28419/? E/wyn: onSubscribe thread is Thread-2
2019-01-18 11:33:17.026 28398-28398/com.example.RxThread D/wyn: onNext is 0
2019-01-18 11:33:17.027 28398-28398/com.example.RxThread E/wyn: onNext thread is main
2019-01-18 11:33:17.029 28398-28398/com.example.RxThread E/wyn: onComplete
2019-01-18 11:33:17.030 28398-28398/com.example.RxThread E/wyn: onComplete thread is main
复制代码
timer设置延迟的时间,而后在主线程更新界面。
通常轮询接口获取数据或倒计时显示内容,使用TimerTask来实现,而后采用Handler发送Message更新界面。
private void testInterval() {
Observable.interval(3, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this.observer);
}
复制代码
输出结果:
2019-01-18 11:41:42.108 29064-29064/? E/wyn: onSubscribe
2019-01-18 11:41:42.108 29064-29064/? E/wyn: onSubscribe thread is main
2019-01-18 11:41:45.115 29064-29064/com.example.RxThread D/wyn: onNext is 0
2019-01-18 11:41:45.115 29064-29064/com.example.RxThread E/wyn: onNext thread is main
2019-01-18 11:41:48.112 29064-29064/com.example.RxThread D/wyn: onNext is 1
2019-01-18 11:41:48.112 29064-29064/com.example.RxThread E/wyn: onNext thread is main
2019-01-18 11:41:51.113 29064-29064/com.example.RxThread D/wyn: onNext is 2
2019-01-18 11:41:51.114 29064-29064/com.example.RxThread E/wyn: onNext thread is main
2019-01-18 11:41:54.113 29064-29064/com.example.RxThread D/wyn: onNext is 3
2019-01-18 11:41:54.114 29064-29064/com.example.RxThread E/wyn: onNext thread is main
.......
复制代码
interval间隔指定的时间,在主线程执行操做。
测试代码中使用到的observer和observerString,
private Observer<Long> observer = new Observer<Long>() {
Disposable disposable;
@Override
public void onSubscribe(Disposable d) {
Log.e("wyn", "onSubscribe");
Log.e("wyn", "onSubscribe thread is " + Thread.currentThread().getName());
disposable = d;
}
@Override
public void onNext(Long s) {
Log.d("wyn", "onNext is " + s);
Log.e("wyn", "onNext thread is " + Thread.currentThread().getName());
tvContent.setText(s + "");
if (s == 10) {
disposable.dispose();
}
}
@Override
public void onError(Throwable e) {
Log.e("wyn", "onError");
Log.e("wyn", "onError thread is " + Thread.currentThread().getName());
}
@Override
public void onComplete() {
Log.e("wyn", "onComplete");
Log.e("wyn", "onComplete thread is " + Thread.currentThread().getName());
}
};
private Observer<String> observerString = new Observer<String>() {
Disposable disposable;
@Override
public void onSubscribe(Disposable d) {
Log.e("wyn", "onSubscribe");
Log.e("wyn", "onSubscribe thread is " + Thread.currentThread().getName());
disposable = d;
}
@Override
public void onNext(String s) {
Log.d("wyn", "onNext is " + s);
Log.e("wyn", "onNext thread is " + Thread.currentThread().getName());
tvContent.setText(s);
}
@Override
public void onError(Throwable e) {
Log.e("wyn", "onError");
Log.e("wyn", "onError thread is " + Thread.currentThread().getName());
}
@Override
public void onComplete() {
Log.e("wyn", "onComplete");
Log.e("wyn", "onComplete thread is " + Thread.currentThread().getName());
}
};
复制代码
选择子线程操做的时候,若是有文件操做那么必定要用Schedulers.io()
。否则建议使用Schedulers.computation()
.
从友盟统计iOS和Android的崩溃来看,Android的空指针崩溃真的是多如牛毛啊。为啥不整一个nil类型,从系统级别上,进行全局的空指针的保护呢!少一点崩溃,多一点快乐!!!
// END