Handler-Message-Looper核心原理

2020-07-23  本文已影响0人  菠萝好吃

核心部分

核心有两个部分:调用通知者发送Message和Handler所在线程接受处理Message

1.发送Message

Handler是调用的核心类。

*使用Handler.sendMessage()发送message消息

*Handler中调用当前线程的looper.enqueueMessage

*MessageQueue插入Message;

以上就完成了发送message基本操作。

2.接收处理Message

Looper为核心中转控制。

*Looper.Loop()开启一个死循环。

*循环中等待MessageQueue返回message

*有返回,则通过msg.target.dispatchmessage回调给Hanlder以及调用者;

以上完成接收处理Message。

细节详解

1.发送Message细节

*Handler中通过sendMessage()发送message消息,也能通过post(Runnable r),本质上post中,也是把Runnable进行一层封装,多了一个回调;

*Handler使用Looper类时,并不是直接new,而且通过Looper.myLooper();

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

public static @Nullable Looper myLooper() { return sThreadLocal.get();}

使用了ThreadLocal,不同线程取到不同Looper实例,一个Looper实例对应一个MessageQueue列表;做到了线程间的消息队列隔离

*MessageQueue类中通过Message的next属性,将他们组成一个单向链表。enqueueMessage将Message加入队列。如果Message没有特殊就直接加入队列尾,而如果前面Hanlder中使用了sendMessageDelayed,指定了时间,则会在遍历链表过程中,选择合适点插入,此处有用到Message的when属性。

另外一个很重要点,enqueueMessage中遍历循环后,需要判断是否要唤醒队列,主要根据当前是否mBlocked堵塞。唤醒使用nativeWake()。此方法对应nativePollOnce(),都是C层原生方法 。类似Object的notify()和wait(),但底层原理又有所不同。

2.接收处理Message细节

Looper.Loop()开启一个死循环,在for循环中不断调用Looper.MessageQueue.next()等待返回message。

next()中,通过nativePollOnce()进行等待。nativePollOnce()本质关键为使用linux中的epoll多路IO复用。

等待返回message后,msg.target.dispatchmessage回调给Hanlder以及调用者。

最后继续循环等待。

3.总结

Hanlder为一个对外封装类,方便调用者使用。

Looper找到当前线程的MessageQueue和开启Loop循环。

MessageQueue消息队列,管理插入Message和返回Message,等待和唤醒实现都是c层。


上一篇下一篇

猜你喜欢

热点阅读