异步多线程

延迟触发

循环定时触发

一、前言

项目开发中一定会用到网络请求,文件读写,开启子线程进行耗时操作,延迟返回或关闭提示框,轮询接口获取处理结果,子线程发送内容到主线程更新界面等等。碰到这些问题或需求的时候,每位程序猿都会使用自己喜欢或习惯的用法来实现或界面问题。当然结果是功能完成了或问题修复了。但是代码风格的差异,使用时考虑不全,使用方法不是最优,等等多多少少存在一些瑕疵。例如:阿里的java编程规范不推荐显式使用Thread

直接使用AsyncTask存在内存泄露或者weak用法导致空指针的问题

使用Handler进行更新界面的复杂操作

使用postDelayed()进行延迟操作不能在子线程中使用

使用TimerTask进行轮询时复杂的更新页面

综上,特别想在代码上统一用法,并且是简单又安全,而且性能最优。所以想到RxJava是不是可以来实现这个愿望。尝试和研究中记录的Demo,有使用错误或更好的方案,请多指教。

二、 铺垫

1. RxJava集成

项目中先集成RxJava库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中的使用。

2. RxJava多线程

3. Scheduler

针对多线程的操作,Schedulers的参数了解,请参考我所理解的RxJava——上手其实很简单(三);

三、异步

最直接的用法就是new Thread()创建一个子线程,然后用EventMessage或Handler发送Message来更新页面。更好一点的方法是ExecutorService创建线程池,统一管理线程并且复用线程以及控制线程的总数,但是需要再花点时间维护和优化。但是不建议为每一个Activity或fragment创建一个线程池,从性能和线程复用率上没有必要性。private void testCreate() {

Observable.create(new ObservableOnSubscribe() {

@Override

public void subscribe(ObservableEmitter emitter) throws Exception {

Log.e("wyn", "ObservableEmitter");

Log.e("wyn", "ObservableEmitter thread is " + Thread.currentThread().getName());

long a = 1;

for (int i = 0; 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);

}

打印的结果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 observer = new Observer() {

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 observerString = new Observer() {

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作者:蝴蝶之梦天使

链接:https://www.jianshu.com/p/cee49d6d817f

android 开启一个定时线程_Android异步、延迟和定时任务的简易用法相关推荐

  1. android 开启一个定时线程_Android中定时执行任务的3种实现方法

    在android中,有主线程和子线程,子线程不能操作ui进行更改,目前我们不考虑ui问题和线程通信问题,一起跟着爱站技术频道小编的步伐来了解Android中定时执行任务的3种实现方法. 在Androi ...

  2. android 开启一个定时线程_ANDROID开发中定时器的3种方法

    在android中,经常用到的定时器主要有以下几种实现: 一.采用Handler与线程的sleep(long )方法 二.采用Handler的postDelayed(Runnable, long) 方 ...

  3. android 开启一个定时线程_Android 定时任务刷新的多种实现方式

    1.采用Handle与线程的sleep(long)方法 1) 定义一个Handler类,用于处理接受到的Message. Handler handler = new Handler() { publi ...

  4. android 开启一个定时线程_Android 定时器实现方式

    在Android开发中,定时器一般有以下3种实现方法: 一.采用Handler与线程的sleep(long)方法 二.采用Handler的postDelayed(Runnable, long)方法 三 ...

  5. 第一节:复习委托,并且通过委托的异步调用开启一个新线程和异步回调、异步等待。

    一. 再谈委托 1. 委托是一个关键字为delegate的自定义类型,通过委托可以把方法以参数的形式传递给另外一个方法,实现插件式的开发模式: 同时调用委托的时候,委托所包含的所有方法都会被实现. 2 ...

  6. 第一节:复习委托,并且通过委托的异步调用开启一个新线程和异步回调、异步等待

    一. 再谈委托 1. 委托是一个关键字为delegate的自定义类型,通过委托可以把方法以参数的形式传递给另外一个方法,实现插件式的开发模式: 同时调用委托的时候,委托所包含的所有方法都会被实现. 2 ...

  7. Android开发实践:线程与异步任务

    基于移动客户端的软件特别强调实时性,Android程序更是如此,任何一个程序超过5s没有响应,都会被系统强制杀掉.而且Android也不允许在UI线程中进行任何网络操作,否则就会产生NetworkOn ...

  8. android queue用法,GitHub - rygz146/TQueue: Android 可以任意切换线程的任务队列, TQueue

    TQueue 一个Android开发库, 可以任意切换线程的链式调用任务队列, 可添加定时, 延时任务, 统一异常处理(Ceased中断),但不影响整个任务链的运行. 具体用法如下: TQueue.q ...

  9. 11.定时任务定时线程池详解

    3.1 新增定时任务池 11.定时任务&定时线程池详解 ​ 当我们不用任务框架时,我们想自己写一个定时任务时,我们能想起那个工具类呢?Timer ?还有吗?不知道了,下面我们要讲下Schedu ...

最新文章

  1. 可以连上网,能Ping通网关和DNS服务器,但是却不能访问网页
  2. Linux_用户和权限管理
  3. 华清远见智能小车视频服务器,华清远见版世界杯足球对抗赛,智能小车C位出道...
  4. Java中怎样使用反射根据属性名获取和设置属性的值
  5. ustc小道消息20211227
  6. Android 软键盘的全面解析,让你不再怕控件被遮盖
  7. npm ERR! cb() never called!
  8. 技术MBA打造中国未来CTO
  9. 忆往昔,惜光阴似箭,不堪回首
  10. DES算法的加解密原理(详细算法+样例Demo)
  11. 第11.25节 Python正则表达式编译re.compile及正则对象使用
  12. [C75][こすぷれ喫茶娘々]アマツカミの巫女-妖狐戦奇譚 汉化补丁
  13. 系统默认环境变量PATH设置
  14. ctfshow每周挑战-极限命令执行
  15. vs2010出现“请确保已安装Microsoft SQL Server Compact 3.5,并且没有其它应用程序正在访问该文件 ”
  16. 第6章函数-6 缩写词(20分)
  17. cad坐标归零lisp_CAD图怎么归零
  18. ROS系列——Ubuntu18.04下ros Melodic安装mavros过程中遇到问题及解决-定期更新版
  19. 北大和人大两年整理出来的书单(经济&管理&商业)
  20. 毕业论文的论文致谢与编写

热门文章

  1. Python解决ModuleNotFoundError: No module named ‘Queue‘的问题
  2. 解决Clover在win 10下的兼容问题
  3. 如何在GitHub上重命名存储库?
  4. JSON和JSONP有什么区别?
  5. 异步/等待-什么时候返回Task vs void?
  6. 对象是空的吗? [重复]
  7. linux运维基础2
  8. Rushcrm:客户关系管理适合的才是好的
  9. Android使用XUtils框架上传照片(一张或多张)和文本,server接收照片和文字(无乱码)...
  10. 不该被忽视的CoreJava细节(四)