我是靠谱客的博主 淡淡路人,这篇文章主要介绍Handler消息机制-FWK层Handler消息机制-FWK层,现在分享给大家,希望可以做个参考。

Handler消息机制-FWK层

android12-release


1. 功能简介概要

1.1 简介概要

frameworks/base/core/java/android/os/Handler.java
frameworks/base/core/java/android/os/Looper.java
frameworks/base/core/java/android/os/MessageQueue.java
frameworks/base/core/java/android/os/Message.java

  Activity中UI组件中的信息传递Handler,Android为了线程安全,并不允许我们在UI线程外操作UI;很多时候我们做界面刷新都需要通过Handler来通知UI组件更新!除了用Handler完成界面更新外,还可以使用runOnUiThread()来更新,甚至更高级的事务总线,当然,这里我们只讲解Handler。


  当我们的子线程想修改Activity中的UI组件时,我们可以新建一个Handler对象,通过这个对象向主线程发送信息;而我们发送的信息会先到主线程的MessageQueue进行等待,由Looper按先入先出顺序取出,再根据message对象的what属性分发给对应的Handler进行处理!

  • Handler: 作用就是发送与处理信息,如果希望Handler正常工作,在当前线程中要有一个Looper对象
  • Message: Handler接收与处理的消息对象
  • MessageQueue: 消息队列,先进先出管理Message,在初始化Looper对象时会创建一个与之关联的MessageQueue
  • Looper: 每个线程只能够有一个Looper,管理MessageQueue,不断地从中取出Message分发给对应的Handler处理

1.2 使用案例

UI线程就是我们的主线程,系统在创建Activity UI线程的时候会初始化一个Looper对象,同时也会创建一个与其关联的MessageQueue

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MainActivity extends Activity { final Handler myHandler = new Handler() { @Override public void handleMessage(Message msg) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }

子线中使用需要先执行Looper.prepare() 初始化一个Looper对象,Looper的构造方法中会创建一个MessageQueue对象,再将Looper对象保存到当前线程TLS(Thread Local Storage)。Looper.prepare()在每个线程只允许执行一次。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class SubThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { //TODO 定义消息处理逻辑. } }; Looper.loop(); } }

1.2.1 UI线程初始化Looper

  • Looper.prepareMainLooper() 在fork创建创建进程回调ActivityThread.main(),Activity UI线程初始化一个Looper对象
    在这里插入图片描述
  • prepare(false)表示当前Looper不允许退出,也就是主线的Looper是不允许退出;prepare()默认调用prepare(true),表示的是这个Looper允许退出。
    在这里插入图片描述

frameworks/base/core/java/android/app/ActivityThread.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static void main(String[] args) { // ... ... Looper.prepareMainLooper(); // ... ... ActivityThread thread = new ActivityThread(); thread.attach(false, startSeq); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } // End of event ActivityThreadMain. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }

1.3 大致流程

在这里插入图片描述

2. 流程分析

2.1 相关类之间大致关系

  1. Handler包含Loooper和MessageQueue
  2. Looper包含MessageQueue
  3. MessageQueue包含Message;这里需要关注mPtr = nativeInit(),连接Native层
  4. Message包含Handler,使用Handler.obtainMessage()获取
    在这里插入图片描述

2.2 obtainMessage获取Message

上面1.2 使用案例说过初始化注意事项,这里说一下Message获取
  在使用Handler时,通常是通过Handler.obtainMessage()来获取Message对象的,而其内部调用的是Message.obtain()方法,那么问题来了,为什么不直接new一个Message,而是通过Message的静态方法obtain()来得到的呢?

  使用obtain获取Message对象是因为Message内部维护了一个数据缓存池,回收的Message不会被立马销毁,而是放入了缓存池,在获取Message时会先从缓存池中去获取,缓存池为null才会去创建新的Message。
在这里插入图片描述 在这里插入图片描述

这里也会把Handler给到Message,如果缓存池为null或直接new Message(),Message中变量target:Handler也会在Handler.sendMessage(msg)是赋值
在这里插入图片描述

2.3 消息发送sendMessage、Looper.loop处理目标handler.dispatchMessage

Handler消息发送最终都会调用MessageQueue.enqueueMessage()handler.sendMessage --> sendMessageDelayed --> sendMessageAtTime --> enqueueMessage --> queue.enqueueMessage
在这里插入图片描述

loop()进入循环模式,不断重复下面的操作,直到没有消息时退出循环

  1. 读取MessageQueue的下一条Message;
  2. 把Message分发给相应的Handler target;
  3. msg.recycleUnchecked()把分发后的Message回收到消息池,以便重复利用。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private static boolean loopOnce(final Looper me, final long ident, final int thresholdOverride) { Message msg = me.mQueue.next(); // might block // ... ... final Observer observer = sObserver; // ... ... if (observer != null) { token = observer.messageDispatchStarting(); } long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid); try { msg.target.dispatchMessage(msg); if (observer != null) { observer.messageDispatched(token, msg); } dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0; } catch (Exception exception) { if (observer != null) { observer.dispatchingThrewException(token, msg, exception); } throw exception; } finally { // ... ... } // ... ... msg.recycleUnchecked(); return true; }

2.4 Looper唤醒(MessageQueue连接Native层)

  • sendMessage时可以触发nativeWake(mPtr)
  • Message msg = me.mQueue.next() loop() 获取MessageQueue队列消息时触发先触发nativePollOnce(ptr, nextPollTimeoutMillis)阻塞操作

通过MessageQueue调用native层中执行mLooper->wake()唤醒
在这里插入图片描述

frameworks/base/core/java/android/os/Handler.java
frameworks/base/core/java/android/os/MessageQueue.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
boolean enqueueMessage(Message msg, long when) { // ... ... synchronized (this) { // ... ... // We can assume mPtr != 0 because mQuitting is false. if (needWake) { nativeWake(mPtr); } } return true; }

frameworks/base/core/java/android/os/Looper.java
frameworks/base/core/java/android/os/MessageQueue.java

复制代码
1
2
3
4
5
6
7
8
9
10
private static boolean loopOnce(final Looper me, final long ident, final int thresholdOverride) { Message msg = me.mQueue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return false; } // ... ... }
复制代码
1
2
3
4
5
6
7
8
9
Message next() { // ... ... for (;;) { // ... ... nativePollOnce(ptr, nextPollTimeoutMillis); // ... ... } }

2.4 removeMessages移除Message

  • 最终执行Message.recycleUnchecked();Message没有立马销毁,而是放入了缓存池sPool,缓存池大小MAX_POOL_SIZE = 50,在获取Message时会先从缓存池中去获取。
    在这里插入图片描述 在这里插入图片描述
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void recycleUnchecked() { // Mark the message as in use while it remains in the recycled object pool. // Clear out all other details. flags = FLAG_IN_USE; what = 0; arg1 = 0; arg2 = 0; obj = null; replyTo = null; sendingUid = UID_NONE; workSourceUid = UID_NONE; when = 0; target = null; callback = null; data = null; synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } } }

3. MessageQueue连接Native层 待续~

再次整体查看下大致流程
在这里插入图片描述

最后

以上就是淡淡路人最近收集整理的关于Handler消息机制-FWK层Handler消息机制-FWK层的全部内容,更多相关Handler消息机制-FWK层Handler消息机制-FWK层内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(97)

评论列表共有 0 条评论

立即
投稿
返回
顶部