Handler发送消息的过程

本文详细解析了Android中Handler发送消息的过程,从sendMessage开始,深入到enqueueMessage和enqueueMessage方法,探讨了消息如何进入消息队列,并在消息队列为空和非空时,如何唤醒应用程序主线程进行消息处理。涉及的关键点包括nativeWake方法、C++层的Looper.cpp以及epoll机制。

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

Handler发送消息的过程

当消息队列和消息循环创建好了之后,就可以往消息队列发送消息,定义好msg之后,就通过mHandler.sendMessage(msg)来发送消息

Created with Raphaël 2.1.2HandlerHandlerMessageQueueMessageQueueandorid_os_MessageQueueandorid_os_MessageQueueLooperLoopersendMessageDelayedsendMessageAtTimeenqueueMessageenqueueMessagenativeWakeandroid_os_MessageQueue_nativeWakewakewake

下面具体分析下:
首先从sendMessage开始,然后调用sendMessageDelayed,sendMessageAtTime,enqueueMessage继续处理

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

enqueueMessage()方法首先设置了这个消息的目标处理对象target,即这个消息最终由谁来处理,这里赋值为this,表示这个消息最终由目前发送的Handle来处理,接着enqueueMessage方法调用enqueueMessage方法来把这个消息加入到应用程序的消息队列中去,queue是一个MessageQueue对象

  boolean enqueueMessage(Message msg, long when) {
        synchronized (this) {
            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w(TAG, e.getMessage(), e);
                msg.recycle();
                return false;
            }

            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }

            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

enqueueMessage方法中if和else判断,if分支表示目前消息队列为空,这时应用程序主线程处于空闲状态,也就是说它在等待消息的发送,这时如果有消息就把消息放在消息队列的前面,接着唤醒应用程序的主线程。而else分支表示,消息队列不为空,还有消息在处理,这时候不要唤醒应用程序主线程。nativeWake方法是一个native方法,

static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr) {
    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
    nativeMessageQueue->wake();
}
void NativeMessageQueue::wake() {
    mLooper->wake();
}

NativeMessageQueue类的wake函数,又通过调用C++层mLooper对象的wake()函数进一步操作

void Looper::wake() {
#if DEBUG_POLL_AND_WAKE
    ALOGD("%p ~ wake", this);
#endif

    uint64_t inc = 1;
    ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
    if (nWrite != sizeof(uint64_t)) {
        if (errno != EAGAIN) {
            ALOGW("Could not write wake signal, errno=%d", errno);
        }
    }
}

Looper.cpp里的wake()函数通过如下代码调用:
ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
write()函数,mWakeEventFd就发生了一个event事件,这时前面监听的epoll机制就起了作用,会唤醒应用程序主线程,于是应用程序主线程就会从前面的C++层的Looper类的polllner()函数一层层返回,最后返回到java层的MessageQueue类的next()方法中
发送消息就介绍完了,创建消息对列和消息循环可参考上一篇文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值