IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> android message handler -> 正文阅读

[移动开发]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***等,相关功能也比较完善。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-12-23 15:51:56  更:2021-12-23 15:53:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:09:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码