Handler消息机制(native层)

本文详细探讨了Android Handler消息机制在native层的实现,包括MessageQueue的nativeInit、nativePollOnce和nativeWake方法。介绍了如何通过eventfd创建唤醒文件描述符,利用epoll实现线程间的等待与唤醒,以及消息的处理流程。同时阐述了nativeWake方法的作用,它是如何唤醒等待的主线程来处理新消息的。
摘要由CSDN通过智能技术生成

Handler消息机制(native层)

1.简介

在介绍Handler消息机制(Java层)时,我们看到了Java层的MessageQueue中调用了几个native方法。除此之外,native层也有一套完善的消息机制,用于处理native的消息。

首先来看下native层handler消息的类图:

Natvie层Handler消息类图

从图中可以看到,native层的消息机制关键元素和Java层的消息机制的关键元素基本一致,分别包括LooperMessageQueueHandlerMessage这几个关键元素。除了MessageQueue是Java层与Native层相关联的,其余的几个元素都是不相关联的,但元素的功能基本是一致的,只是Java层和Natvie层的实现方式不一样的。

接下来将从MessageQueue中的native方法开始分析Native层的Handler消息机制。

2.MessageQueue的native方法

在Java层的MessageQueue中定义了几个native方法:

public final class MessageQueue {
    ......
    private native static long nativeInit();
    private native static void nativeDestroy(long ptr);
    private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
    private native static void nativeWake(long ptr);
    private native static boolean nativeIsPolling(long ptr);
    private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
    ......
}
nativeInit方法

在构建Java层的MessageQueue时,会调用nativeInit()方法进行初始化。

2.1 MessageQueue()

MessageQueue(boolean quitAllowed) {
    mQuitAllowed = quitAllowed;
    mPtr = nativeInit();// 保存native层的MessageQueue引用,见2.1
}

在构建MessageQueue的过程中,会通过JNI调用native层的android_os_MessageQueue_nativeInit方法进行初始化。

2.2 android_os_MessageQueue_nativeInit()

static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
    NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();// 构建MessageQueue,见2.3
    if (!nativeMessageQueue) {
        jniThrowRuntimeException(env, "Unable to allocate native queue");
        return 0;
    }

    nativeMessageQueue->incStrong(env);
    return reinterpret_cast<jlong>(nativeMessageQueue);//返回到Java层
}

2.3 NativeMessageQueue()

NativeMessageQueue::NativeMessageQueue() :
    mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
    mLooper = Looper::getForThread();//获取该线程关联的Looper
    if (mLooper == NULL) {
        mLooper = new Looper(false);// 创建一个Looper对象,见2.4
        Looper::setForThread(mLooper);// 将该Looper保存到线程的TLS中
    }
}

在Native层的MessageQueue中,包含了一个Looper对象,该Looper对象是与线程相关的,保存在线程的TLS中,这个与Java层的处理方式一样。如果该线程的Looper对象存在,则直接返回;如果不存在,则创建一个Looper,并保存到该线程的TLS中。

2.4 Looper()

Looper::Looper(bool allowNonCallbacks) :
    mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
    mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
    mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
mWakeEventFd = eventfd(0, EFD_NONBLOCK);// 构建一个唤醒事件的文件描述符fd

AutoMutex _l(mLock);
rebuildEpollLocked();// 重构epoll事件,见2.5
}

eventfd函数会创建一个事件对象(eventfd object),用来实现进程(线程)间的等待(wait)/通知(notify)机制(Linux管道pipe也可以实现该功能),内核会为这个对象维护一个64位的计数器。eventfd的函数定义如下:

#include<sys/eventfd.h>  
int eventfd(unsigned int initval,int flags);

第一个参数initval用来初始化这个计数器,一般初始化为0;
第二个参数为标志位,可选的值为ÿ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值