Android 的 Handler 机制是一个核心组件,用于在 Android 应用程序中执行异步操作和在不同线程之间传递消息。Handler 机制主要由以下几个部分组成:
-
Handler:Handler 是一个用于发送和处理消息和 Runnable 对象的类。它通常与一个线程相关联,并负责将消息插入到与之关联的线程的消息队列中。开发者可以创建 Handler 的子类并重写其 handleMessage() 方法,以便在接收到消息时执行特定操作。
-
Message:Message 是一个包含消息数据和元信息的轻量级对象。它通常包含一个唯一的整数类型(用于区分不同的消息)以及一些其他可选的数据字段,如对象和整数值。通过 Handler 的 sendMessage() 方法,可以将消息发送到消息队列。
-
MessageQueue:MessageQueue 是一个消息队列,用于存储和管理待处理的消息。每个线程都可以有一个与之关联的 MessageQueue,它负责存储该线程上的所有待处理消息。
-
Looper:Looper 是一个循环处理消息队列中消息的类。每个线程都可以有一个与之关联的 Looper。当 Looper 启动时,它会从消息队列中获取下一个待处理的消息,然后将其分发给相应的 Handler。这个过程会一直持续,直到 Looper 被终止。
Android 的 Handler 机制通常用于以下场景:
- 在后台线程上执行耗时操作,如网络请求或数据库操作,然后将结果发送回主线程以更新 UI。
- 在主线程上延迟执行某个任务。
- 在两个不同的线程之间传递数据。
这种机制允许开发者在不阻塞主线程的情况下执行异步操作,从而提高应用程序的性能和响应速度。
底层实现
- Looper.java依赖于system/core/libutils/目录中的looper.cpp文件. 而此处的looper的pollonce实现主要依赖于 epoll 来监听文件描述符上的事件
需要注意的是, 在framework的native层有个Alooper.cpp, 实现了基本同样的api, 但是使用条件变量和互斥锁实现线程同步和事件通知的.
备注
- 一个应用主线程大部分时间是阻塞在nativePollOnce()调用上的. 不管是屏幕事件还是ui自动生成的事件, 触发主线程执行的入口都是在nativePollOnce()醒来, 取消息队列中的新的消息message
如果是屏幕input消息, 是通过ViewRootImpl中enqueueInputEvent()将事件封装好, 放入消息队列, 唤醒阻塞的ui线程重新执行. - Choreographer类中将将回调函数添加到主线程的消息队列, 唤醒主线程执行.
private void postCallbackDelayedInternal(int callbackType, Object token, long delayMillis) {
.....
synchronized (mLock) {
final long now = SystemClock.uptimeMillis();
final long dueTime = now + delayMillis;
Message msg = Message.obtain(mHandler, callbackType, token);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, dueTime);
}
}
msg.setAsynchronous(true)
这句设置表示将 Message 标记为异步消息。在 Android 的消息处理机制中,消息分为同步和异步两种类型。
同步消息(Message 的默认类型)在消息队列中保持顺序,意味着同步消息会按照它们添加到队列的顺序来执行。当处理同步消息时,如果一个消息正在执行,其他同步消息将等待当前消息处理完毕。
异步消息则不会阻塞队列。当一个异步消息处理时,其他异步消息可以跳过同步消息继续执行。这样可以减少异步消息的等待时间,提高响应速度。异步消息通常用于那些对延迟敏感的操作,例如动画和输入事件处理。
通过调用 msg.setAsynchronous(true)
,我们将 Message 标记为异步消息,以确保处理 VSync 相关的回调时具有更高的响应性。
网友评论