android message handler

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***等,相关功能也比较完善。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值