系统handler 是在ActivityThread中定义的,变量名是mH(继承了Handler)
该handler是系统Handler,会接收一些系统的消息,并处理之(如四大主件的生命周期的管理)。
Message(消息)
消息中不仅可以包含自定义的附加的arg1,arg2,obj,还可以绑定一个Runnable类型的对象(Callback),注意,可以使用Handler的post方法直接回调该对象,注意,此时仅仅运行了该Runnable的run方法,并不会启动新的线程。

通常使用它来进行一些循环类的操作,如倒计时类的轮播图等。直接使用post开始循环,或者使用removeCallbacks(Runnable)很方便的取消循环。
消息的产生
Message在系统中是以消息池的形式管理的,消息池是用链表结构实现的。每次从Message.obtain()获取消息。
方法实现如下:

发现链表第一个是用sPool(头指针)来指向的,每次从链表取消息的时候,首先让新msg从sPool来获取,然后sPool移到链表下一个Message对象,新取出的Message初始化各种标记,池子大小减一。

消息的发送:
消息是由Handler的sendMessage方法发送到消息队列中的,该方法有很多重载:

其中的各种sendEmptyMessage其实内部也会生成一个Message对象,只不过该对象没有其他附加字段而已。

可以看到有很多延迟的消息发送方法,也就说消息不仅可以追加到队列末尾,还可以插入到队头,所以消息发送到消息队列时是可以”插队”的,具体的“插队”方法是由enqueueMessage(queue,msg,uptimeMillis)实现的。
消息的处理:
谈到消息的处理过程就要从Looper的loop方法开始看了,

其中dispatchMessage方法实现:

从上图我们看到我们通常复写的handler的handleMessage方法就是在dispatchMessage内部调用的。
注意:loop循环中从消息队列中取消息 queue.next() 其不一定是从队列的头部来取,还要看该消息有没有设置延迟,如果该消息设置了延迟时间为0,那么立即取出该消息执行,否则等待延迟时间到达后再取出执行。(具体请参考next方法具体实现),此处也再次验证了前面“消息的发送”段落说的消息是可以插队的说法。
消息的回收:
回收方法:
消息(Message)是循环使用的,上面介绍了消息的产生和处理,那么消息是如何回收的呢。其实具体的回收方法是在ActivityThread的recycle方法中进行的,

(在消息链表头上加入一个元素)看到使用synchronized拿到池子,然后 让next指向头指针, 再让刚刚加进来的消息作为头指针,然后池子消息数量加一。
回收时机
消息的回收是由系统进行的,并不需要我们手动回收,由于消息的产生和传递过程是:Message.obtain()-->msg.target.dispatchMessage(msg)-->msg.recycleUnchecked()(回收)。
从前面处理过程的图片中可以看到回收是在我们已经对消息处理完成之后进行的(肯定得等消息处理完了再回收,要不还玩儿个毛线)。
总结
在消息泵Looper的作用下消息的整体流程如下:

网友评论