Android消息机制Handler用法总结
作者:天若子 发布时间:2022-08-10 23:58:56
1.简述
Handler消息机制主要包括: MessageQueue、 Handler、 Looper、Message。
Message:需要传递的消息,可以传递数据;
MessageQueue:消息队列,但是它的内部实现并不是用的队列,而是通过单链表的数据结构来维护消息列表,因为单链表在插入和删除上比较有优势。主要功能是向消息池投递消息( MessageQueue.enqueueMessage)和取走消息池的消息( MessageQueue.next)。
Handler:消息辅助类,主要功能是向消息池发送各种消息事件( Handler.sendMessage)和处理相应消息事件( Handler.handleMessage);
Looper:消息控制器,不断循环执行( Looper.loop),从MessageQueue中读取消息,按分发机制将消息分发给目标处理者。
2.异步线程切换原理
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
每一个异步线程,都维护着唯一的一个Looper,每一个Looper会初始化(维护)一个MessageQueue,之后进入一个无限循环一直在读取MessageQueue中存储的消息,如果没有消息那就一直阻塞等待。
我们在实例化handler的过程中,会先得到当前所在线程的looper对象,之后得到与该looper对象相对应的消息队列,看源码Handler中持有Looper、MessageQueue。
private static void handleCallback(Message message) {
message.callback.run();
}
final Looper mLooper;
final MessageQueue mQueue;
final Callback mCallback;
当我们发送消息的时候,即handler.sendMessage或者handler.post,会将msg中的target赋值为handler自身,这就是实现message从一个线程到另外一个线程的传递的本质,之后加入到消息队列中。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
我们一般会重写handlerMessage方法处理消息,这将会在msg.target.disPatchMessage方法中被回调,从而实现了message从一个线程到另外一个线程的传递。
3.总结
1.Handler 的背后有 Looper、MessageQueue 支撑,Looper 负责消息分发,MessageQueue 负责消息管理;
2.在创建 Handler 之前一定需要先创建 Looper,Looper 有退出的功能,但是主线程的 Looper 不允许退出;
3.异步线程Looper,Looper.prepare()创建Looper,Looper.loop()开始轮询,需要自己调用 Looper.myLooper().quit()退出;
4.Runnable 被封装进了 Message,可以说是一个特殊的 Message;
5.Handler.handleMessage() 所在的线程是 Looper.loop() 方法被调用的线程;
6.Handler内存泄漏的原因
原因:MessageQueue持有Message,Message持有activity,delay多久,message就会持有activity多久。
解决方案:静态内部类、弱引用,最后不要忘记调用Handler.removeCallbacksAndMessages(null)清空所有消息。
public class SampleActivity extends Activity {
/**
* Instances of static inner classes do not hold an implicit
* reference to their outer class.
*/
private static class MyHandler extends Handler {
private final WeakReference<SampleActivity> mActivity;
public MyHandler(SampleActivity activity) {
mActivity = new WeakReference<SampleActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
SampleActivity activity = mActivity.get();
if (activity != null) {
// ...
}
}
}
// MyHandler
private final MyHandler mHandler = new MyHandler(this);
/**
* Instances of anonymous classes do not hold an implicit
* reference to their outer class when they are "static".
*/
private static final Runnable sRunnable = new Runnable() {
@Override
public void run() { /* ... */ }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Post a message and delay its execution for 10 minutes.
mHandler.postDelayed(sRunnable, 1000 * 60 * 10);
// Go back to the previous Activity.
finish();
}
@Override
protected void onDestroy() {
super.onDestroy();
//mHandler.removeCallbacksAndMessages(null);
}
}
以上所述是小编给大家介绍的Android消息机制Handler用法总结网站的支持!
来源:https://blog.csdn.net/zhukui66/article/details/121505150


猜你喜欢
- 1. 前言不知道小伙伴对于日期字段,在项目中都是如何处理的,是单独给每个字段都自定义日期格式还是做全局格式设置?这个我之前啊,是
- 在拿到一个 Stream 如何优雅将这个 Stream 保存到代码最优雅的方法应该是通过 CopyTo 或 CopyToAsync 的方法u
- 早期的项目比较简单,多是用JSP 、Servlet + JDBC 直接搞定,后来使用 Struts1(Struts2)+Spring+Hib
- 配置准备在build.gradle文件中添加如下依赖: compile "org.elasticsearc
- 大家对于 Spring 的 scope 应该都不会默认。所谓 scope,字面理解就是“作用域”、“范围”,如果一个 bean 的 scop
- API:接口概念:API(Application Programming Interface),应用程序编程接口,Java API是一本程序
- 本文实例为大家分享了C#汉字转换为拼音缩写的实现代码,供大家参考,具体内容如下using System;using System.Confi
- 首先提出这样一个问题:如果两个对象不相同,他们的hashCode值一定不相等吗?我们都知道equals和hashCode是Object中的方
- 快速排序类using System;using System.Data;using System.Config
- 本文总结了Java的关键字与标识符。分享给大家供大家参考,具体如下:相关内容:关键字:定义特点用于定义数据类型的关键字用于定义流程控制的关键
- Android数据存储几种方式SharePreferences数据库SQLite存储卡的文件操作Application一、共享参数Share
- 通过拍照或相册中获取图片,并进行裁剪操作,然后把图片显示到ImageView上。 当然也可以上传到服务器(项目中绝大部分情况是上传
- 概述@SpringBootTest注解是SpringBoot自1.4.0版本开始引入的一个用于测试的注解。基本用法如下:1. 添加Maven
- 一、问题描述平时我们在完成某些数据的入库后,发布了一个事件,此时使用的是@EventListener,然后在这个事件中,又去对刚才入库的数据
- 引言C#应用通过 Microsoft.Toolkit.Uwp.Notifications NuGet包可以很方便的发送本地通知(Window
- 1|1简介最近基于最新的Activiti7配置了SpringBoot2。简单上手使用了一番。发现市面上解决Activiti7的教程很少,采坑
- 在一次源码查看ThreadGroup的时候,看到一段代码,为以下:/* * @throws NullPointer
- 本文实例讲述了C#使用ToUpper()与ToLower()方法将字符串进行大小写转换的方法。分享给大家供大家参考。具体分析如下:C#通过T
- 如果没有安装过maven,是用的idea自带的maven,那就是idea的安装目录下 /plugins/maven/lib/maven3这个
- Spring事务传递机制原理首先,我们通过org.springframework.transaction.annotation.Propag