1 Android 提供了一套异步处理消息机制;
有提供两套的实现方案:java side和cpp side
java side:
Handler / Message/Looper/MessageQueue
code 路径:
frameworks/base/core/java/android/os/Looper.java
frameworks/base/core/java/android/os/Message.java
frameworks/base/core/java/android/os/Handler.java
frameworks/base/core/java/android/os/MessageQueue.java
frameworks/base/core/jni/android_os_MessageQueue.cpp
cpp side--Looper.cpp
code 路径:
system/core/libutils/Looper.cpp
2 简述相关类的功能:
Handler 是消息的处理类,每个message都指定该消息交由谁处理
Message是消息的封装
Looper是消息的马达,(简单说内部有for循环一直做轮询),该类与thread 有关系。
MessageQueue是消息队列的入口
cpp 端Looper: 一个类里面封装了handler/message/消息队列的相关实现。同时向java side 提供wait/poll的逻辑和对fd的监听动作。
4 提供下相关类的图
5 详细的调用结构
Handler:-- 构造函数中会获取相应的looper
obtainMessage
- Message.obtain
postAtTime
- sendMessageAtTime
- enqueueMessage
- MessageQueue.enqueueMessage
removeMessages
- mQueue.removeMessages
hasMessages
- mQueue.hasMessages
Handler.runWithScissors
如果调用thread不同于handler的thread,会由等待handler thread 执行完成后再通知回来
runWithScissors( Runnable r, long timeout):
- Looper.myLooper() == mLooper
- r.run();
- Return
- br= new BlockingRunnable(r) //这边是再调用thread中处理,new BlockingRunnable
- br.postAndWait(this, timeout)
BlockingRunnable.postAndWait :
- handler.post(this)// 这边往handler post自己, handler执行到自己的run方法
- wait(delay)// 调用thread 会wait
BlockingRunnable.run
- mTask.run() // handler thread中执行task的run方法
- notifyAll() // hanlder thread执行完 notify 调用线程停止wait
Looper.java
Looper.prepare---线程创建后需要调用该方法,初始化相关消息机制
- prepare(boolean quitAllowed)
- sThreadLocal.set(new Looper(quitAllowed));
- new MessageQueue
- nativeInt --JNI
- new NativeMessageQueue
- new Looper.cpp
Looper.loop()
- myLooper()
- for (;;) {
- loopOnce
- mQueue.next() // 调用MessageQueue的next,里面有wait
- msg.target.dispatchMessage(msg);
- msg.recycleUnchecked()
Looper.myLooper().quit()
Looper.myLooper().quitSafely()
- mQueue.quit
MessageQueue
MessageQueue.next
- for (;;) {
- nativePollOnce(ptr, nextPollTimeoutMillis);
- 遍历Message
- msg != null && !msg.isAsynchronous()
- now < msg.when
- Set nextPollTimeoutMillis
- now >= msg.when
- 更新message queue:pre->next = msg->next
- msg.markInUse();
- Return msg
- mQuitting=true:dispose()
MessageQueue.enqueueMessage
- mQuitting = true: return
- 更新msg: msg.markInUs() / set when
- 更新message queue:
- 如果空,设置mMessage
- 非空:按when 排序,插入到链表中
MessageQueue.hasMessage/removeMessages 都是遍历message 链表的操作
MessageQueue.quit(boolean safe)
- mQuitting=true : return
- Safe=true: removeAllFutureMessagesLocked
- Safe=false: removeAllMessagesLocked
- nativeWake
MessageQueue.addOnFileDescriptorEventListener
removeOnFileDescriptorEventListener
updateOnFileDescriptorEventListenerLocked
- 都是调用updateOnFileDescriptorEventListenerLocked实现更新操作
- 使用mFileDescriptorRecords[SparseArray]保存相关的fd及event操作,更新创建或删除相关的FileDescriptorRecord
- nativeSetFileDescriptorEvents 更新到native层
MessageQueue.dispatchEvents ---- Called from native code
- record = mFileDescriptorRecords.get(fd);
- listener = record.mListener;
- listener.onFileDescriptorEvents( record.mDescriptor, events);
- newWatchedEvents != oldWatchedEvents & newWatchedEvents == 0 : mFileDescriptorRecords.removeAt(index)
Looper.cpp ---- 真正的驱动类
Looper 类内部实现了java 层的msg/handler/thread 相关的功能,并且真正有实现wait和wake的功能。
1 Looper 类中定义了一个数据结构vector 存储消息列表。Vector<MessageEnvelope> mMessageEnvelopes;
2 每个thread保证只有一个Looper在跑,通过以下几个linux API实现:
pthread_key_create /pthread_setspecific/pthread_getspecific
3 使用epoll 实现的timeout和监听fd的逻辑: pollOnce epoll_wait
4 wake 使用pipe 的方式,往fd中写data,唤醒epoll的wait逻辑
5 可以addFd 去监听fd的逻辑
epoll_ctl(fd, EPOLL_CTL_ADD/EPOLL_CTL_MOD/EPOLL_CTL_DEL)
6 综述:
1 java side 的message 都是存储在MessageQueue中,MessageQueue里面使用链表的方式将java side msg 连接起来.
2 java side 使用MessageQueue与cpp的Looper 进行绑定,通过Looper实现pollOnce和wake的功能。
3 java side也有监听fd的功能,接口是在MessageQueue中,不过真正实现还是Looper.cpp中,可以使用如下方式
Looper.myLooper().getQueue.addOnFileDescriptorEventListener
4 使用new Handler 的方式创建的handler,其looper对应的thread的是调用new的thread。
5 java side 几个类的关系:
Handler---1:1-----Looper ----1:1----- MessageQueue---1:1---Looper.cpp
MessageQueue ---- 1: N ---Message ---1:1-----Handler
所以MessageQueue中的handler 可以是不同的,但handler 必须都是同一个thread的。
6 CPP 层消息机制都是在Looper一个类中定义的,其接口基本直接使用的是linux 接口:epoll_wait/epoll_ctrl/ pthread_create***等,相关功能也比较完善。