android管理机制,Android任务管理机制

本文详细介绍了Android消息机制,涉及Message、MessageQueue、Looper、Handler这4个类,阐述了它们的功能及类间关系。还介绍了线程本地存储区、主线程驱动、消息生产与消费等内容,以及IdleHandler和Native层消息机制,包括Java层与Native层的关联和消息处理流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

消息机制涉及MessageQueue/Message/Looper/Handler这4个类。

说明

Message:消息分为硬件产生的消息(如按钮、触摸)和软件生成的消息;,Message有自己的缓存池,避免message的频繁创建销毁

MessageQueue:消息队列的主要功能向消息池投递消息(MessageQueue.enqueueMessage)和取走消息池的消息(MessageQueue.next);

Handler:消息辅助类,主要功能向消息池发送各种消息事件(Handler.sendMessage)和处理相应消息事件(Handler.handleMessage);

Looper:不断循环执行(Looper.loop),按分发机制将消息分发给目标处理者。

类关系

Looper有一个MessageQueue消息队列;

MessageQueue有一组待处理的Message;

Message中有一个用于处理消息的Handler;

Handler中有Looper和MessageQueue;

ThreadLocal

线程本地存储区(Thread Local Storage,简称为TLS),每个线程都有自己的私有的本地存储区域,不同线程之间彼此不能访问对方的TLS区域。

每个线程可以有多个TLS,一个TLS对应一个value

Looper 创建就以TLS方式创建,一个线程中最多只能有1个Looper

主线程驱动

主线程最终就是调用Looper的loop方法进入死循环,进行消息驱动

主线程的Looper 是在 ActivityThread main函数中创建的

public static void main(String[] args) {

// Install selective syscall interception

AndroidOs.install();

// CloseGuard defaults to true and can be quite spammy. We

// disable it here, but selectively enable it later (via

// StrictMode) on debug builds, but using DropBox, not logs.

CloseGuard.setEnabled(false);

Environment.initForCurrentUser();

// Make sure TrustedCertificateStore looks in the right place for CA certificates

final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());

TrustedCertificateStore.setDefaultUserDirectory(configDir);

Process.setArgV0("");

Looper.prepareMainLooper();

// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.

// It will be in the format "seq=114"

long startSeq = 0;

if (args != null) {

for (int i = args.length - 1; i >= 0; --i) {

if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {

startSeq = Long.parseLong(

args[i].substring(PROC_START_SEQ_IDENT.length()));

}

}

}

ActivityThread thread = new ActivityThread();

thread.attach(false, startSeq);

if (sMainThreadHandler == null) {

sMainThreadHandler = thread.getHandler();

}

if (false) {

Looper.myLooper().setMessageLogging(new

LogPrinter(Log.DEBUG, "ActivityThread"));

}

Looper.loop();

throw new RuntimeException("Main thread loop unexpectedly exited");

}

消息生产

handler::enqueueMessage,MessageQueue是按照Message触发时间的先后顺序排列的,队头的消息是将要最早触发的消息。当有消息需要加入消息队列时,会从队列头开始遍历,直到找到消息应该插入的合适位置,以保证所有消息的时间顺序。

消息消费(在loop中)

读取MessageQueue的下一条Message;

Message next() {

final long ptr = mPtr;

if (ptr == 0) { //当消息循环已经退出,则直接返回

return null;

}

int pendingIdleHandlerCount = -1; // 循环迭代的首次为-1

int nextPollTimeoutMillis = 0;

for (;;) {

if (nextPollTimeoutMillis != 0) {

Binder.flushPendingCommands();

}

//nativePollOnce是阻塞操作,其中nextPollTimeoutMillis代表下一个消息到来前,还需要等待的时长;当nextPollTimeoutMillis = -1时,表示消息队列中无消息,会一直等待下去。

nativePollOnce(ptr, nextPollTimeoutMillis);

synchronized (this) {

final long now = SystemClock.uptimeMillis();

Message prevMsg = null;

Message msg = mMessages;

//当消息的Handler为空时,则查询异步消息

if (msg != null && msg.target == null) {

//当查询到异步消息,则立刻退出循环

do {

prevMsg = msg;

msg = msg.next;

} while (msg != null && !msg.isAsynchronous());

}

if (msg != null) {

if (now < msg.when) {

//当异步消息触发时间大于当前时间,则设置下一次轮询的超时时长

nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);

} else {

// 获取一条消息,并返回

mBlocked = false;

if (prevMsg != null) {

prevMsg.next = msg.next;

} else {

mMessages = msg.next;

}

msg.next = null;

//设置消息的使用状态,即flags |= FLAG_IN_USE

msg.markInUse();

return msg; //成功地获取MessageQueue中的下一条即将要执行的消息

}

} else {

//没有消息

nextPollTimeoutMillis = -1;

}

//消息正在退出,返回null

if (mQuitting) {

dispose();

return null;

}

//当消息队列为空,或者是消息队列的第一个消息时

if (pendingIdleHandlerCount < 0 && (mMessages == null || now < mMessages.when)) {

pendingIdleHandlerCount = mIdleHandlers.size();

}

if (pendingIdleHandlerCount <= 0) {

//没有idle handlers 需要运行,则循环并等待。

mBlocked = true;

continue;

}

if (mPendingIdleHandlers == null) {

mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];

}

mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);

}

//只有第一次循环时,会运行idle handlers,执行完成后,重置pendingIdleHandlerCount为0.

for (int i = 0; i < pendingIdleHandlerCount; i++) {

final IdleHandler idler = mPendingIdleHandlers[i];

mPendingIdleHandlers[i] = null; //去掉handler的引用

boolean keep = false;

try {

keep = idler.queueIdle(); //idle时执行的方法

} catch (Throwable t) {

Log.wtf(TAG, "IdleHandler threw exception", t);

}

if (!keep) {

synchronized (this) {

mIdleHandlers.remove(idler);

}

}

}

//重置idle handler个数为0,以保证不会再次重复运行

pendingIdleHandlerCount = 0;

//当调用一个空闲handler时,一个新message能够被分发,因此无需等待可以直接查询pending message.

nextPollTimeoutMillis = 0;

}

}

把Message分发给相应的target;

再把分发后的Message回收到消息池,以便重复利用。

IdleHandler

每次在获取下一个message时,没有获取到时执行idleHnalder的runable

整体流程

62bbb03e5170

handler_java.jpg

Handler通过sendMessage()发送Message到MessageQueue队列;

Looper通过loop(),不断提取出达到触发条件的Message,并将Message交给target来处理;

经过dispatchMessage()后,交回给Handler的handleMessage()来进行相应地处理。

将Message加入MessageQueue时,处往管道写入字符,可以会唤醒loop线程;如果MessageQueue中没有Message,并处于Idle状态,则会执行IdelHandler接口中的方法,往往用于做一些清理性地工作。

Native 层 消息机制

在整个消息机制中,而MessageQueue是连接Java层和Native层的纽带,换言之,Java层可以向MessageQueue消息队列中添加消息,Native层也可以向MessageQueue消息队列中添加消息,接下来来看看MessageQueue。

62bbb03e5170

handler_arch.png

红色虚线关系:Java层和Native层的MessageQueue通过JNI建立关联,彼此之间能相互调用,搞明白这个互调关系,也就搞明白了Java如何调用C++代码,C++代码又是如何调用Java代码。

蓝色虚线关系:Handler/Looper/Message这三大类Java层与Native层并没有任何的真正关联,只是分别在Java层和Native层的handler消息模型中具有相似的功能。都是彼此独立的,各自实现相应的逻辑。

WeakMessageHandler继承于MessageHandler类,NativeMessageQueue继承于MessageQueue类

MessageQueue通过mPtr变量保存NativeMessageQueue对象,从而使得MessageQueue成为Java层和Native层的枢纽,既能处理上层消息,也能处理native层消息;下面列举Java层与Native层的对应图

另外,消息处理流程是先处理Native Message,再处理Native Request,最后处理Java Message。理解了该流程,也就明白有时上层消息很少,但响应时间却较长的真正原因。

Native Message:和java层类似,由native的

Native Request: 由fd触发的event,这些文件描述符可以让其他组件注册,发送

refrence

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值