(Android7.0源码剖析)android Handler机制,从java到c++

handler是用looper轮询消息的。

那么我们此次分析的重点就是分析Looper.loop方法。

首先从looper的loop方法开始


因为loop要不断地接受消息。

此时有两种方案

1.一种是死循环不停的去判断有没有消息

2.通过wait/notify方法,让线程阻塞,当子线程发出消息时,调用notify方法通知主线程接收消息

显示,第二种方案效率高得多,looper又是一个常用功能,所以必须做出一个极限的效率优化。


早在Android2.2的时代,loop方法用的是java里object类里的wait方法等待消息的。这里不详细介绍。

在Android2.3以后(目前Android推出8.0),loop的核心实现都用jni藏在c++里,那么接下来我们详细的分析一下c++层



1.首先java层的Looper.loop方法里有一个for(;;),循环执行MessageQueue的next()方法取到消息

2.MessageQueue类的next方法通过调用nativePollOnce方法获取msg

3.android_os_MessageQueue_nativePollOnce方法通过调用了pollOnce方法,我们继续跟踪调用栈

4.pollOnce调用了mLooper的pollOnce方法,我们在跟进。

5.pollOnce调用pollInner方法

6.pollInner方法里面调用了epoll_wait方法,这个方法跟java的wait方法的功能类似,都是让线程阻塞。

到这里我们终于看到了裸漏在外的epoll,

那么epoll是什么呢?

epoll实现了线程阻塞,跟java的wait方法的功能相似。

因为epoll拥有优秀的效率,乃至成为一种轮询时的标准,所以在著名的轮询使用场景中都有epoll方法的身影。

比如包括nginx在内的大多数服务器轮询接受客户端的请求。

我模仿Looper写了一个最简单的epoll使用方式,献上代码,https://github.com/ChinaTengFei/easyLooper

代码很简单,创建了几个子线程一个主线程,子线程通过epoll跟主线程进行通讯。

那么此时我们知道了jni层是如何实现线程的阻塞,我们也知道了轮询的原理。接下来分析下子线程发消息的代码

从Handler.java的sendMessageAtTime开始分析,

~ sendMessageAtTime方法间接调用了MessageQueueen的queueMessage方法

~ 在queueMessage方法中最后有一个if判断,if(needWake)

~ needWake=需要唤醒

~ 正常情况下needWake为true,那么就调用nativeWake方法唤醒主线程

下面是c++层

~ nativeWake调用了NativeMessageQueue类的wake方法

~ wake方法调用了Looper的wake方法:mLooper->wake();

~ wake方法调用write方法写入数据。

~ 此时epoll监听到有数据写入。就把数据返回到java层。
同样写入数据也可以参考我的这个小demo,https://github.com/ChinaTengFei/easyLooper

你可能感兴趣的:((Android7.0源码剖析)android Handler机制,从java到c++)