Android之Handler、Message、MessageQueue、Looper详解1

简介: Android之Handler、Message、MessageQueue、Looper详解

Handler

Handler的原理

Handler的原理:Android中主线程是不能进行耗时操作的,子线程是不能进行更新UI的。所以就有了Handler,它的作用就是实现线程之间的通信。


Handler整个流程中,主要有四个对象,handler,Message,MessageQueue,Looper。当应用创建的时候,就会在主线程中创建handler对象,我们通过要传送的消息保存到Message中,handler通过调用sendMessage方法将Message发送到MessageQueue中,Looper对象就会不断的调用loop()方法 不断的从MessageQueue中取出Message交给handler进行处理。从而实现线程之间的通信。


线程间通信的实现步骤

线程间通信的实现步骤:

  1. 在主线程中定义Handler的子类
  2. 重写Handler类的handleMessage()方法
  3. 用该子类定义全局的Handler对象,以便子线程使用
  4. 子线程获得handler对象用该对象的sendMessage()方法发送消息

Handler在多线程中的应用

  1. 发送消息,在不同的线程间发送消息,使用的方法为sendXXX();android.os.Handler对象通过下面的方法发送消息的:

sendEmptyMessage(int):发送一个空的消息;

sendMessage(Message):发送消息,消息中可以携带参数;

sendMessageAtTime(Message, long):未来某一时间点发送消息;

sendMessageDelayed(Message, long):延时Nms发送消息。

计划任务,在未来执行某任务,使用的方法为postXXX();。

android.os.Handler对象通过下面的方法执行计划任务:

post(Runnable):提交计划任务马上执行;

postAtTime(Runnable, long):提交计划任务在未来的时间点执行;

postDelayed(Runnable, long):提交计划任务延时Nms执行。

如何在子线程中创建Handler

如何在子线程中创建Handler?

创建一个 HandlerThread,即创建一个包含 Looper 的线程HandlerThread 的构造函数有两个

通过 HandlerThread 的 getLooper 方法可以获取 Looper

通过 Looper 我们就可以创建子线程的 handler 了

通过该 handler 发送消息,就会在子线程执行;

如果要 handlerThread 停止: handlerThread.quit();

Hander中removeMessages方法

Hander中removeMessages方法

这个方法使用的前提是之前调用过sendEmptyMessageDelayed(0, time),意思是延迟time执行handler中msg.what=0的方法;

在延迟时间未到的前提下,执行removeMessages(0),则上面的handler中msg.what=0的方法取消执行;

在延迟时间已到,handler中msg.what=0的方法已执行,再执行removeMessages(0),不起作用。

该方法会将handler对应message队列里的消息清空,通过msg.what来找到对应的message。

当队列中没有message则handler会不工作,但并不是handler会停止,当队列中有新的message进来后,会继续处理执行。

Handler内存泄漏

Handler发生内存泄漏的情况

Handler发生内存泄漏的情况:非静态内部类,或者匿名内部类。

使得Handler默认持有外部类的引用。在Activity销毁时,由于Handler可能有未执行完/正在执行的Message。导致Handler持有Activity的引用。进而导致GC无法回收Activity

发送延迟消息

第一种情况,是通过handler发送延迟消息,我们在HandlerActivity中,发送一个延迟20s的消息。然后打开HandlerActivity后,马上finish。看看会不会内存泄漏。

我们的HandlerActivity发生了内存泄漏,从引用路径来看,是被匿名内部类的实例mHandler持有引用了,而Handler的引用是被Message持有了,Message引用是被MessageQueue持有了…

结合我们所学的Handler知识和这次引用路径分析,这次内存泄漏完整的引用链应该是:

主线程 —> threadlocal —> Looper —> MessageQueue —> Message —> Handler —> Activity

所以这次引用的头头就是主线程,主线程肯定是不会被回收的,只要是运行中的线程都不会被JVM回收,跟静态变量一样被JVM特殊照顾。

子线程运行没结束

第二个实例,是我们常用到的,在子线程中工作,比如请求网络,然后请求成功后通过Handler进行UI更新运行中的子线程 —> Activity

当然,这里的Handler也是持有了Activity的引用的,但主要引起内存泄漏的原因还是在于子线程本身,就算子线程中不用Handler,而是调用Activity的其他变量或者方法还是会发生内存泄漏。

所以这种情况我觉得不能看作Handler引起内存泄漏的情况,其根本原因是因为子线程引起的,如果解决了子线程的内存泄漏,比如在Activity销毁的时候停止子线程,那么Activity就能正常被回收,那么也不存在Handler的问题了

解决内存泄漏

解决内存泄漏

不要让长生命周期对象持有短生命周期对象的引用,而是用长生命周期对象持有长生命周期对象的引用

比如Glide使用的时候传的上下文不要用Activity而改用Application的上下文(这句有问题,并无此说法,在此修正)。还有单例模式不要传入Activity上下文

将对象的强引用改成弱引用

强引用就是对象被强引用后,无论如何都不会被回收。 弱引用就是在垃圾回收时,如果这个对象只被弱引用关联(没有任何强引用关联他),那么这个对象就会被回收。 所以我们将对象改成弱引用,就能保证在垃圾回收时被正常回收。软引用就是在系统将发生内存溢出的时候,回进行回收。 虚引用是对象完全不会对其生存时间构成影响,也无法通过虚引用来获取对象实例,用的比较少

内部类写成静态类或者外部类

跟上面Hanlder情况一样,有时候内部类被不正当使用,容易发生内存泄漏,解决办法就是写成外部类或者静态内部类

在短周期结束的时候将可能发生内存泄漏的地方移除

比如Handler延迟消息,资源没关闭,集合没清理等等引起的内存泄漏,只要在Activity关闭的时候进行消除即可

Android之Handler、Message、MessageQueue、Looper详解2:https://developer.aliyun.com/article/1473573

目录
相关文章
|
2月前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
|
2月前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
59 1
|
2月前
|
消息中间件 存储 Java
Android消息处理机制(Handler+Looper+Message+MessageQueue)
Android消息处理机制(Handler+Looper+Message+MessageQueue)
60 2
|
消息中间件 存储 机器学习/深度学习
【Android】Handler 机制 ( Handler | Message | Looper | MessageQueue )(二)
【Android】Handler 机制 ( Handler | Message | Looper | MessageQueue )(二)
143 0
|
消息中间件 存储 调度
【Android】Handler 机制 ( Handler | Message | Looper | MessageQueue )(一)
【Android】Handler 机制 ( Handler | Message | Looper | MessageQueue )(一)
181 0
|
19天前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
40 19
|
19天前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
43 14