Android|Android 消息机制源码分析

我们知道,当应用启动的时候,android首先会开启一个主线程,主线程管理ui控件,进行事件分发,当我们要做一个耗时的操作时,如联网读取数据,获取读取本地较大的文件的时候,你应该在子线程中操作,因为有ui的更新,android主线程是线程不安全的,如果将更新界面放在子线程中是危险的,必须在主线程中执行,这个时候引出Handler,Handler运行在主线程,他与子线程通过message对象来传递数据.
Message类

Message类: 用来携带数据的载体 public int what; //标识 public int arg1; //携带int类型数据 public int arg2; //携带int类型数据 public Object obj; //携带任意对象数据 long when; //保存要被处理的时间点 Handler target; //处理消息的handler Runnable callback; //处理消息的回调器对象 Message next; //用来保存引用的下一个message(才能形成链表) private static Message sPool; //存储处理过的消息的池 //在需要Message对象时复用

Message.obtain(); //从消息池中获取空消息对象




说明:
1.我们要获取空消息对象时最好通过Message.obtain()方法从消息池中取消息,而不是它的构造器,这样可以更好的复用消息对象,以节约内存。
2.如果Message要携带int型的数据时,可以使用它的arg属性
3.Message 中的target即为处理消息的handler
4.what 为标识信息类别


Handler类

sendMessage(Message msg); sendEmptyMessage(int what); sendMessageDelayed(Message msg, long delayMillis) sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); //当前时间+延迟时间 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; //处理消息Handler就是发送消息的handler if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); //将消息添加到消息队列中 }public final void removeMessages(int what) {//移除队列中未被处理的消息 mQueue.removeMessages(this, what, null); }public void dispatchMessage(Message msg) { if (msg.callback != null) { //如果message内部有回调处理器, 直接交给它处理 handleCallback(msg); } else { if (mCallback != null) {//如果Handler内部有回调处理器, 交给它处理, 如果返回true才结束, 否则继续 if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); //调用Handler的回调方法处理 } }

需要注意的是:
1.handler可以在任意线程发送消息,这些消息都将添加到MessageQueue中
2.handler实在关联了looper的线程中处理消息的,当然主线程也是一个looper线程


MessageQueue

enqueueMessage(Message msg, long when) { msg.when = when; //将消息被处理的时间保存在msg上//将msg对象保存到mMessages链表中一个合适的位置nativeWake(mPtr); //唤醒处理等待状态下的程序 //不是通过wait()来实现的, 而是通过C/C++的代码来实现的, 不会阻塞主线程 }Message next() { //从消息队列中取出需要处理的消息, 如果没有进入等待状态(没有阻塞主线程)}



Looper
looper线程的创建

public class LooperThread extends Thread { @Override public void run() { // 将当前线程初始化为Looper线程 Looper.prepare(); ...// 开始循环处理消息队列 Looper.loop(); } }



looper的一些属性

public class Looper { private static final ThreadLocal sThreadLocal = new ThreadLocal(); // 每个线程中的Looper对象其实是一个ThreadLocalfinal MessageQueue mQueue; // Looper内的消息队列Thread mThread; // 当前线程





private Looper() { // 创建Looper对象中的消息队列,和它所属的线程 mQueue = new MessageQueue(); mRun = true; mThread = Thread.currentThread(); }





创建looper对象方法
public static final void prepare() { if (sThreadLocal.get() != null) {throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); }




static void loop() { final MessageQueue queue = me.mQueue; //拿到消息队列 Message msg = queue.next(); // might block从队列中取出当前需要处理的消息} //将message对象交给handler分发处理 msg.target.dispatchMessage(msg); msg.recycle(); //回收处理过消息: 清理内部数据, 并添加为消息池的第一个消息



【Android|Android 消息机制源码分析】这样我们就把消息队列中的几个重要的对象简单的过了一边。

    推荐阅读