前言
多线程的应用在Android开发中是非常常见的,常用方法主要有:
- 继承Thread类
- 实现Runnable接口
- Handler
- AsyncTask
- HandlerThread
今天,我将全面解析多线程其中一种常见用法:HandlerThread
由于本文涉及多线程知识和Handler源码解析,所以阅读本文前建议先看:
Android开发:Handler异步通信机制全面解析(包含Looper、Message Queue)
多线程完全总结
目录
1. 定义
- Android API提供的一个封装类
- 继承自Thread类
2. 作用
- 通过继承Thread类,实现快速地创建一个带有Looper的新工作线程的功能
- 通过对Handler类使用的封装,实现快速创建Handler并与其他线程进行通信的功能
总结
HandlerThread本质上是通过继承Thread类和封装Handler类的使用,从而使得创建新线程和与其他线程进行通信变得更加方便易用
3. 使用对比
3.1 Thread+Handler用法
因为HandlerThread本质上是继承Thread类和对Handler类使用的封装,所以我们先来看下一般情况下使用Thread+Handler创建线程的用法:
- 使用Thread类创建一个新的线程
- 通过创建Handler与其他线程进行通信
如果你还没阅读过Handler的源码,强烈建议先看文章:
Android开发:Handler异步通信机制全面解析(包含Looper、Message Queue)
Thread+Handler的一般用法
|
|
在注释里已经非常清晰了,接下来我将继续介绍更加方便易用的HandlerThread
3.2 HandlerThread用法
- HandlerThread的本质:继承Thread类和对Handler类使用的封装。
- 我们先来看HandlerThread的具体使用步骤
|
|
- 是不是感觉 HandlerThread更加清晰、简单、易用?!
- 接下来,我们开始对HandlerThread的用法进行源码分析,看一下HandlerThread是如何通过继承Thread类和封装Handler类用法从而使得多线程通信变得如此方便。
4. HandlerThread源码分析
结合HandlerThread上面的用法和本质来看,其实主要是分析:
- 如何创建新线程,即分析
|
|
- 如何创建Handler并进行通信,即分析
|
|
- 如何结束线程,即分析
|
|
以下是HandlerThread类的源码(注释标注得非常清晰)
|
|
注意:
- 在获得mLooper对象的时候存在一个同步的问题:只有当线程创建成功并且Looper对象也创建成功之后才能获得mLooper的值,才能将创建的Handler与该Looper绑定
- 解决方案:在run()中成功创建Looper对象后,立即调用notifyAll()通知 getLooper()中的wait()结束等待,并返回run()中成功创建的Looper对象,使得Handler与该Looper对象绑定
5. 实例使用
5.1 实例说明:
- 目的:点击按钮实现延迟操作并更新UI组件
- 使用方法:HandlerThread类
在看下面例子之前我建议你们先去下载Demo,边下边读效果更佳哦!
5.2 具体代码
- 主布局文件
activity_main.xml
|
|
- MainActivity文件
MainActivity.java(注释已经标注得非常清楚)
|
|
5.3 运行结果
5.4 特别注意
从上面的例子中会出现两个细节问题:
5.4.1 细节问题1:内存泄露
在上面的例子中,你会发现出现了严重的警告:
|
|
即造成了严重的内存泄漏,关于Handler的内存泄露请参考XXX
5.4.2 细节问题2:连续发送消息
- 当你连续点击3下时,发现并没有马上按照最新点击的按钮的操作去显示,而是按顺序的一个个显示出来
- 原因:使用HandlerThread时只是开了一个工作线程,当你点击了x下后,只是将x个消息发送到消息队列MessageQueue里排队,等候派发消息给Handler再进行对应的操作
5.5 Demo的源码地址
源码地址放在Github上:Demo for HandlerThread
6. 总结
- 本文主要对多线程HandlerThread的用法和源码进行了全面介绍
- 接下来,我会继续讲解Android开发中关于多线程的知识,包括继承Thread类、实现Runnable接口、Handler等等,有兴趣可以继续关注Carson_Ho的安卓开发笔记
欢迎关注Carson_Ho的简书!
不定期分享关于安卓开发的干货,追求短、平、快,但却不缺深度。