Android Handler机制笔记

本文深入解析了Android消息机制,包括Looper的初始化、无限循环处理、MessageQueue的创建、JNI层的管道实现以及消息的发送与接收流程。详细阐述了如何通过管道和Epoll实现线程间的通信,确保消息的高效分发。
摘要由CSDN通过智能技术生成
1.初始化MainLooper,保存在静态变量ThreadLocal里面
ActivityThread.java
Looper.prepareMainLooper();
	prepare();
		sThreadLocal.set(new Looper());
			mQueue = new MessageQueue();
	setMainLooper(myLooper());
		myLooper() = (Looper)sThreadLocal.get();

2.开启无限循环。
Looper.loop();

3.MessageQueue初始化
MessageQueue();
	nativeInit();
		NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
			new Looper(); // 创建JNI层Looper;
		setNativeMessageQueue();
			// 通过反射把Java层的MessageQueue里面的mPtr变量设置成JNI层的
			// NativeMessageQueue的指针.方便调用时找到是哪个
			env->SetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr,
             reinterpret_cast<jint>(nativeMessageQueue));	

4. JNI层Looper初始化
简单来说,管道就是一个文件,在管道的两端,分别是两个打开文件文件描述符,这两个打开文件描述符都是对应同一个文件,
其中一个是用来读的,别一个是用来写的,一般的使用方式就是,一个线程通过读文件描述符中来读管道的内容,当管道没有内容时,
这个线程就会进入等待状态,而另外一个线程通过写文件描述符来向管道中写入内容,写入内容的时候,
如果另一端正有线程正在等待管道中的内容,那么这个线程就会被唤醒。

Looper::Looper(bool allowNonCallbacks);
	int wakeFds[2];
	int result = pipe(wakeFds);
	mWakeReadPipeFd = wakeFds[0];
	mWakeWritePipeFd = wakeFds[1];
	// EPOLL_SIZE_HINT 能监控的最大描述符数量
	mEpollFd = epoll_create(EPOLL_SIZE_HINT);
	......
 
	struct epoll_event eventItem;
	memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
	eventItem.events = EPOLLIN;
	eventItem.data.fd = mWakeReadPipeFd;
	// 监控管道的读端
	result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);

5. 这里只做了两件事,取消息和分发消息
Looper.loop();
	Looper me = myLooper();
	MessageQueue queue = me.mQueue;
	while (true) {
			Message msg = queue.next(); // might block

			if (msg != null) {
				if (msg.target == null) {
					// No target is a magic identifier for the quit message.
					return;
				}
				msg.target.dispatchMessage(msg);
				msg.recycle();
			}
		}


6. 取消息
MessageQueue.next();
	nativePollOnce(mPtr, nextPollTimeoutMillis);	// nextPollTimeoutMillis 取值有 0 n>0 -1 0: 不等待 n>0: 等待n毫秒后自动唤醒; -1: 无限等待
	NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);	// 通过mPtr找到对应的JNI层的MQ
    nativeMessageQueue->pollOnce(timeoutMillis);
    	mLooper->pollOnce(timeoutMillis);
    		result = pollInner(timeoutMillis);
    			// 等待在这个位置 eventCount > 0 说明会有监控事件
    			int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
    			for (int i = 0; i < eventCount; i++) {
    				int fd = eventItems[i].data.fd;
    				uint32_t epollEvents = eventItems[i].events;
    				if (fd == mWakeReadPipeFd) {
    					if (epollEvents & EPOLLIN) {
    						awoken();	// 把管道的内容读取出来
    					}
    				}
    			}

7. 发消息 以及唤醒第六步阻塞的位置 唤醒后,走第五步分发流程
mq.enqueueMessage(msg, uptimeMillis);
	nativeWake(mPtr);
		NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
    	return nativeMessageQueue->wake();
    		ssize_t nWrite;
			do {
				nWrite = write(mWakeWritePipeFd, "W", 1);
			} while (nWrite == -1 && errno == EINTR);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值