Android 系统(152)---Android多线程:HandlerThread详细使用手册
Android多线程:HandlerThread详细使用手册
前言
多线程的应用在
Android
开发中是非常常见的,常用方法主要有:- 继承Thread类
- 实现Runnable接口
- Handler
- AsyncTask
- HandlerThread
今天,我将全面解析多线程其中一种常见用法:HandlerThread
由于本文涉及多线程知识和Handler源码解析,所以阅读本文前建议先看:
Android开发:Handler异步通信机制全面解析(包含Looper、Message Queue)
目录
1. 定义
一个Android
已封装好的轻量级异步类
2. 作用
- 实现多线程
在工作线程中执行任务,如 耗时任务 - 异步通信、消息传递
实现工作线程 & 主线程(UI
线程)之间的通信,即:将工作线程的执行结果传递给主线程,从而在主线程中执行相关的UI
操作从而保证线程安全
3. 优点
方便实现异步通信,即不需使用 “任务线程(如继承Thread
类) + Handler
”的复杂组合
实际上,HandlerThread本质上是通过继承Thread类和封装Handler类的使用,从而使得创建新线程和与其他线程进行通信变得更加方便易用
4. 工作原理
内部原理 = Thread
类 + Handler
类机制,即:
- 通过继承
Thread
类,快速地创建1个带有Looper
对象的新工作线程 - 通过封装
Handler
类,快速创建Handler
& 与其他线程进行通信
5. 使用步骤
HandlerThread
的本质:继承Thread
类 & 封装Handler
类HandlerThread
的使用步骤分为5步
// 步骤1:创建HandlerThread实例对象
// 传入参数 = 线程名字,作用 = 标记该线程HandlerThread mHandlerThread = new HandlerThread("handlerThread");// 步骤2:启动线程mHandlerThread.start();// 步骤3:创建工作线程Handler & 复写handleMessage()
// 作用:关联HandlerThread的Looper对象、实现消息处理操作 & 与其他线程进行通信
// 注:消息处理操作(HandlerMessage())的执行线程 = mHandlerThread所创建的工作线程中执行Handler workHandler = new Handler( handlerThread.getLooper() ) {@Overridepublic boolean handleMessage(Message msg) {...//消息处理return true;}});// 步骤4:使用工作线程Handler向工作线程的消息队列发送消息
// 在工作线程中,当消息循环时取出对应消息 & 在工作线程执行相关操作// a. 定义要发送的消息Message msg = Message.obtain();msg.what = 2; //消息的标识msg.obj = "B"; // 消息的存放// b. 通过Handler发送消息到其绑定的消息队列workHandler.sendMessage(msg);// 步骤5:结束线程,即停止线程的消息循环mHandlerThread.quit();
6. 实例讲解
下面,我将用一个实例讲解`HandlerThread`该如何使用
6.1 实例说明
- 点击按钮实现延迟操作
- 最终更新UI组件
6.2 具体实现
建议先下载源码再阅读:Carson_Ho的Github:HandlerThread
- 主布局文件:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"tools:context="com.example.carson_ho.handler_learning.MainActivity"><TextView
android:id="@+id/text1"android:layout_centerInParent="true"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="测试结果" /><Button
android:id="@+id/button1"android:layout_centerInParent="true"android:layout_below="@+id/text1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="点击延迟1s + 显示我爱学习"/><Button
android:id="@+id/button2"android:layout_centerInParent="true"android:layout_below="@+id/button1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="点击延迟3s + 显示我不爱学习"/><Button
android:id="@+id/button3"android:layout_centerInParent="true"android:layout_below="@+id/button2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="结束线程的消息循环"/>
</RelativeLayout>
- 主代码文件:MainActivity.java
public class MainActivity extends AppCompatActivity {Handler mainHandler,workHandler;HandlerThread mHandlerThread;TextView text;Button button1,button2,button3;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 显示文本text = (TextView) findViewById(R.id.text1);// 创建与主线程关联的HandlermainHandler = new Handler();/*** 步骤1:创建HandlerThread实例对象* 传入参数 = 线程名字,作用 = 标记该线程*/mHandlerThread = new HandlerThread("handlerThread");/*** 步骤2:启动线程*/mHandlerThread.start();/*** 步骤3:创建工作线程Handler & 复写handleMessage()* 作用:关联HandlerThread的Looper对象、实现消息处理操作 & 与其他线程进行通信* 注:消息处理操作(HandlerMessage())的执行线程 = mHandlerThread所创建的工作线程中执行*/workHandler = new Handler(mHandlerThread.getLooper()){@Override// 消息处理的操作public void handleMessage(Message msg){//设置了两种消息处理操作,通过msg来进行识别switch(msg.what){// 消息1case 1:try {//延时操作Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}// 通过主线程Handler.post方法进行在主线程的UI更新操作mainHandler.post(new Runnable() {@Overridepublic void run () {text.setText("我爱学习");}});break;// 消息2case 2:try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}mainHandler.post(new Runnable() {@Overridepublic void run () {text.setText("我不喜欢学习");}});break;default:break;}}};/*** 步骤4:使用工作线程Handler向工作线程的消息队列发送消息* 在工作线程中,当消息循环时取出对应消息 & 在工作线程执行相关操作*/// 点击Button1button1 = (Button) findViewById(R.id.button1);button1.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 通过sendMessage()发送// a. 定义要发送的消息Message msg = Message.obtain();msg.what = 1; //消息的标识msg.obj = "A"; // 消息的存放// b. 通过Handler发送消息到其绑定的消息队列workHandler.sendMessage(msg);}});// 点击Button2button2 = (Button) findViewById(R.id.button2);button2.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 通过sendMessage()发送// a. 定义要发送的消息Message msg = Message.obtain();msg.what = 2; //消息的标识msg.obj = "B"; // 消息的存放// b. 通过Handler发送消息到其绑定的消息队列workHandler.sendMessage(msg);}});// 点击Button3// 作用:退出消息循环button3 = (Button) findViewById(R.id.button3);button3.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {mHandlerThread.quit();}});}}
- 运行结果
- 源码地址
Carson_Ho的Github:HandlerThread
6.3 特别注意点
细节问题1:内存泄露
- 在上面的例子中,出现了严重的警告:
In Android, Handler classes should be static or leaks might occur.
- 1
- 即造成了严重的内存泄漏,关于Handler的内存泄露请看文章:Android 内存泄露:详解 Handler 内存泄露的原因
细节问题2:连续发送消息
- 当你连续点击3下时,发现并无按照最新点击的按钮操作显示,而是按顺序的一个个显示出来
- 原因:使用
HandlerThread
时只是开了一个工作线程,当你点击了n
下后,只是将n
个消息发送到消息队列MessageQueue
里排队,等候派发消息给Handler再进行对应的操作
7. 源码分析
- 知其然 而须知其所以然,了解
HandlerThread
的源码分析有利于更好地理解HandlerThread
的工作原理 - 具体请看文章:Android多线程:这是一份详细的HandlerThread源码分析攻略
8. 总结
- 本文全面介绍了多线程
HandlerThread
的用法 & 源码 - 接下来,我会继续讲解
Android
开发中关于多线程的知识,包括继承Thread
类、实现Runnable
接口、Handler
等等,有兴趣
Android 系统(152)---Android多线程:HandlerThread详细使用手册相关推荐
- android log抓取方法,Android系统之Android抓取各种log的方法
Android系统之Android抓取各种log的方法 2018年11月25日 | 萬仟网移动技术 | 我要评论 android之android抓取各种log的方法 1.logcat (四类log b ...
- Android系统架构-[Android取经之路]
摘要:本节主要来讲解Android的系统架构 阅读本文大约需要花费10分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢! 欢 ...
- android 服务端技术,移动应用服务器端开发(基于JSP技术)-2017 Android系统构架 Android系统构架.docx...
Android系统构架 PAGE 1 目 录 TOC \o "1-3" \h \z \u 一.Android系统构架 1 二.Linux内核层 2 三.系统运行库层 3 (一)系统 ...
- 【android系统】android系统升级流程分析(二)---update升级包分析
接下来我们将通过几篇文章来分析update.zip包在具体Android系统升级的过程,来理解Android系统中Recovery模式服务的工作原理.今天让我先来分析下升级包update.zip. 一 ...
- 【android系统】android系统升级流程分析(一)---recovery模式中进行update包升级流程分析
今天我们直接来看下android中具体的升级过程是如何的. 升级流程概述 升级的流程图: 升级流程分析 第一步:升级包获取 升级获取可以通过远程下载,也可直接拷贝到指定目录即可. 第二步:准备升级 然 ...
- android系统 PowerManager深入分析(非常详细)
概述 一直以来,电源管理是电子产品设计中非常重要的环节,也是任何电子设备中最为重要的系统模块之一,优秀的电源管理方案,能够提供持久的续航能力,良好的用户体验,更能提升电子产品的竞争力. 移动设备的电量 ...
- android系统语音合成,android 语音合成报错
发现了2个问题 第一个貌似是复制离线的资源出错了(已经核对过读写等权限): 12-19 19:54:49.739 32006-32159/com.zhanglf.youxuanz I/NonBlock ...
- Android 系统(71)---Android系统build.prop文件生成过程
Android系统build.prop文件生成过程 Android系统build.prop生成过程 这个文件类似于windows的注册表文件,定义了系统初始的一些参数属性,功能的开放等,通过调整或增加 ...
- android系统平台,Android系统平台 实用小软件推荐
随着时间的推移,android平台上的软件可谓是越来越丰富;每天各种千奇百怪的.实用的.趣味恶搞的应用层出不穷,要选择一个自己需要的合适自己手机用的软件真是越来越难了.为了各位手机用户们的手机寿命着想 ...
最新文章
- 512 个 AI 职位、11 万美元年薪,盘点 2018 最佳人工智能公司
- noi99钉子和小球 解题报告
- 【Servlet】总结 JSP的四大域对象、Servlet的四个作用域:pageContext、request、session、application
- 世界上覆盖范围最广的计算机网络是 ( ),世界上覆盖范围最广的计算机网络是()。...
- 【原】让两个DIV高度一样的Javascript函数
- 零基础 5 分钟上手,程序员喜提 AIoT 新利器!
- 毕业一年后我转行NLP 这几点宝贵经验分享给大家
- 深圳40K都招不到嵌入式开发人员?
- android解析html新闻的方法,Android使用Jsoup解析Html表格的方法
- depends-on
- HP Proliant DL360 G9使用业务网卡登录ILO管理
- linux万能密码,Linux pam 后门纪录root用户密码以及设置万能密码登录root
- python判断是否闰年_【python】判断年份是否为闰年
- 如何用电脑下载网页中的视频?
- 《吊打面试官》系列-Redis基础
- C语言的s8数据结构
- 【MT19937】学习分析
- B-spline曲线基函数计算Matlab程序
- 身高体重排序-华为OD
- c语言里主函数指什么,C语言里的主函数是什么
热门文章
- STM32学习——EXTI外部中断
- 【STM32】HAL库 STM32CubeMX教程五----看门狗(独立看门狗,窗口看门狗)
- Java学习日报—泳道与Feign—2021/11/30
- 令牌桶算法和漏桶算法python_图解Python算法
- 最长回文子串java_5. 最长回文子串
- 英文简历中的自我评价
- Alley Bird 跳跳鸟源码
- 关于火狐浏览器在ubuntu和安卓手机上的同步
- Hibernate操作数据库步骤(包括语法)
- Linux下部署LVS(DR)+keepalived+Nginx负载均衡