核心部分
核心有两个部分:调用通知者发送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层。
网友评论