Android-HandlerThread使用及源码分析

注:一次OPPO面试的尴尬,所以回来恶补

原文链接借鉴

1 HandlerThread

1.1 主要作用

更简单的将一个一次性的多线程改进成可以循环利用的异步线程(个人理解)

1.2 原理

继承了Thread,实际上是一个使用Looper、Handler的线程。

继承了Thread,在run()方法中通过Looper.prepare()来创建消息队列,Looper.loop()来循环处理消息。

使用时开启HandlerThread,创建Handler与HandlerThread的Looper绑定,Handler以消息的方式通知HandlerThread来执行一个具体的任务。

1.3 特点

HandlerThread将loop转到子线程中处理,说白了就是将分担MainLooper的工作量,降低了主线程的压力,使主界面更流畅。

开启一个线程起到多个线程的作用。处理任务是串行执行,按消息发送顺序进行处理。HandlerThread本质是一个线程,在线程内部,代码是串行处理的。

但是由于每一个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理。

HandlerThread拥有自己的消息队列,它不会干扰或阻塞UI线程。

对于网络IO操作,HandlerThread并不适合,因为它只有一个线程,还得排队一个一个等着。

HandlerThread内部维护了一个消息队列,避免多次创建和销毁子线程来进行操作。

2 HandlerThread的使用

2.1 HandlerThread使用步骤

(1)创建HandlerThread实例,参数字符串定义新线程的名称。

HandlerThread mHandlerThread =newHandlerThread("check-message-coming"); 

(2)启动HandlerThread线程。

mHandlerThread.start();

(3)创建Handler对象,将HandlerThread的Lopper作为参数,这样就完成了Handler对象与HandlerThread的Looper对象的绑定(这里的Handler对象可以看作是绑定在HandlerThread子线程中,所以handlerMessage里的操作是在子线程中运行的)。 重写handleMessage处理耗时操作。

Handler mCheckMsgHandler =newHandler(mHandlerThread.getLooper()){@OverridepublicvoidhandleMessage(Message msg){// 进行耗时操作}};

这样我们就可以使用mCheckMsgHandler对象以处理消息的形式来进行耗时操作,完成以后就可以切换到主线程的handler中来更新UI。

2.2 HandlerThread使用示例

依据刚才的步骤,来实现一个每秒更新数据的一个功能,这个功能可以用来更新股票、商品价格等。

创建和启动HandlerThread,handler绑定:新建Activity,在onCreate()中进行使用一个initBackThread()方法创建HandlerThread。等待mCheckMsgHandler 得到消息开始模拟耗时操作完成后切换到UI线程去更新UI,使用主线程的Handler也是一样的。


Android-HandlerThread使用及源码分析_第1张图片

绑定按钮使用handler发送消息:一个开始按钮使mCheckMsgHandler发送消息去进行耗时操作,另一个按钮停止发送消息。标记isUpdate设置是否再次发送消息更新。

Android-HandlerThread使用及源码分析_第2张图片

要记得在onPause()和onDestroy()中暂停更新和停止mHandlerThread以释放内存。

Android-HandlerThread使用及源码分析_第3张图片

具体的源码分析【转载请注明出处:Android HandlerThread 源码分析 CSDN 废墟的树】

HandlerThread源码分析

HandlerThread构造函数


Android-HandlerThread使用及源码分析_第4张图片

分析:该类开头就给出了一个描述:该类用于创建一个带Looper循环的线程,Looper对象用于创建Handler对象,值得注意的是在创建Handler

对象之前需要调用start()方法启动线程。这里可能有些人会有疑问?为啥需要先调用start()方法之后才能创建Handler呢?后面我们会解答。

上面的代码注释已经很清楚了,HandlerThread类有两个构造方法,不同之处就是设置当前线程的优先级参数。你可以根据自己的情况来设置优先

级,也可以使用默认优先级。

HandlerThread的run方法


Android-HandlerThread使用及源码分析_第5张图片

分析:以上代码中的注释已经写得很清楚了,以上run方法主要作用就是调用了Looper.prepare和Looper.loop构建了一个循环线程。值得一提的

是,run方法中在启动loop循环之前调用了onLooperPrepared方法,该方法的实现是一个空的,用户可以在子类中实现该方法。该方法的作用是

在线程loop之前做一些初始化工作,当然你也可以不实现该方法,具体看需求。由此也可以看出,Google工程师在编写代码时也考虑到代码的可扩展性。牛B!

HandlerThread的其他方法

getLooper获得当前线程的Looper对象


Android-HandlerThread使用及源码分析_第6张图片


分析:其实方法开头的英文注释已经解释的很清楚了:该方法主要作用是获得当前HandlerThread线程中的mLooper对象。

首先判断当前线程是否存活,如果不是存活的,这直接返回null。其次如果当前线程存活的,在判断线程的成员变量mLooper是否为null,如果为

null,说明当前线程已经创建成功,但是还没来得及创建Looper对象,因此,这里会调用wait方法去等待,当run方法中的notifyAll方法调用之后

通知当前线程的wait方法等待结束,跳出循环,获得mLooper对象的值。

总结:在获得mLooper对象的时候存在一个同步的问题,只有当线程创建成功并且Looper对象也创建成功之后才能获得mLooper的值。这里等待方法wait和run方法中的notifyAll方法共同完成同步问题。

quit结束当前线程的循环


Android-HandlerThread使用及源码分析_第7张图片

分析:以上有两种让当前线程退出循环的方法,一种是安全的,一中是不安全的。至于两者有什么区别? quitSafely方法效率比quit方法标率低一点,但是安全。具体选择哪种就要看具体项目了。

总结:

1.HandlerThread适用于构建循环线程。

2.在创建Handler作为HandlerThread线程消息执行者的时候必须调用start方法之后,因为创建Handler需要的Looper参数是从HandlerThread类中获得,而Looper对象的赋值又是在HandlerThread的run方法中创建。

3.关于HandlerThread和Service的结合使用请参考另一篇博客:Android IntentService 源码分析

【转载请注明出处:Android HandlerThread源码分析 CSDN 废墟的树】

你可能感兴趣的:(Android-HandlerThread使用及源码分析)