android的消息机制

时间:2021-12-20 05:40:49

很多以前掌握的知识,总是慢慢的再忘记,看来还是自己理解的不够透彻,希望用博客的形式记录下来。

说起android的消息机制,那不得不提Handler,它的中文含义就是控制者,处理者。
安卓上的关于Handler的文档是这么写的:
Handler可以发送和处理Message,Runnable对象,并且与一个线程的MessageQueue关联。
当创建了Handler实例,它就会绑定在创建它线程的消息队列上。

android的消息机制

首先在主线程中创建Handler的实例,与主线程的MessageQueue绑定,MessageQueue里有一个轮询器Looper,它会不断的查看消息队列是否有消息。如果有消息,就会把这个消息扔给Handler的handleMessage去处理。
这时,子线程拿到Handler对象,往主线程的MessageQueue发消息,消息队列就有了消息,就会把消息扔给handleMessage去处理消息。
上面的过程,听起来十分绕耳。为什么要这么做?在子线程中去处理不行吗?
我们知道子线程一般是用于处理耗时的操作,是不可以更新UI的。
因为多线程同时去draw,去操作UI界面,UI界面实在不好控制。操作UI的动作必须要由主线程去做。

所以在子线程中碰见需要更新UI,我们可以使用android为我们提供的Handler。它的出现主要就是为了解决在子线程中无法访问UI的矛盾。
而如果强行的在子线程去操作UI,可能会出现 “ android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.”的异常。

1,new Handler的时候,Handler究竟做了什么?
android的消息机制

Looper.mylooper()
android的消息机制
android的消息机制
Looper对象是从ThreadLocal集合中get得到的。那什么时候,ThreadLocal把Looper对象set进去的呢?
android的消息机制
在prepare方法中,创建了Looper对象,并添加到了存储着Looper对象的ThreadLocal中。
android的消息机制
而在new Looper的同时,同样也创建了MessageQueue的实例。

而调用prepare方法的是prepareMainLooper。
在应用运行时,主线程ActivityThread产生并执行,而在主线程的main方法中,就会调用prepareMainLooper。
也就是说,在应用一启动,就会去创建Looper,MessageQueue对象。而在Handler的构造方法中,是拿到已经创建好的Looper和MessageQueue。

2,Message消息对象
new Message可以直接创建消息对象。
通过handler.obtainMessage(有许多重载的方法)可以创建消息,翻看源码可以得知,消息的创建全都是由obtain方法去处理。
android的消息机制
这里的sPool表示的是消息池中的第一条消息,当消息池中没有消息时,就会new一个Message返回。
如果消息池中有的话,就废物利用,把消息池中的消息返回。
而消息池中的消息是由Message本身来维护的,而不是MessageQueue。
消息池中的消息是这样摆放的:
android的消息机制
android的消息机制
sPool表示是第一条消息,它指向着a。
Message m=sPool;
这时m也指向了a
sPool=m.next
sPool这时不再指向a,而是指向了下一个消息b。
m.next=null
sPoolSize--
a的next成员变量不再指向b,置为null。消息队列的长度减减,返回消息池中的消息。

3,Looper处理消息的过程
子线程发送消息后,主线程的MessageQueue就有了消息。而消息的扔给Handler去处理,是需要Looper来轮询的。
定位到Looper的轮询消息的loop方法。

 Message msg = queue.next(); // might block
..........
..........
..........
msg.target.dispatchMessage(msg);

从消息队列中取出的消息交由了msg.target这个成员变量的dispatchMessage方法。
而msg.target是Handler类型的。那msg.target是怎么传递进来的:

public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;

return m;
}

该handler在创建Message时,赋予给Handler类型的target。
而在dispatchMessage中,会调用handleMessage。
而在主线程中,我们定义的handleMessage就会覆盖该方法。
所以,Message对象就这样一步一步的传递到了主线程Handler的handleMessage中。
结论就是:消息是由哪个Handler发送的,就由哪个Handler去处理。