Android 消息机制源码分析

来源:互联网 发布:不想找女朋友 知乎 编辑:程序博客网 时间:2024/04/27 06:36

我们知道,当应用启动的时候,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; //处理消息的handlerRunnable 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对象其实是一个ThreadLocal        final 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(); //回收处理过消息: 清理内部数据, 并添加为消息池的第一个消息

这样我们就把消息队列中的几个重要的对象简单的过了一边。

0 0
原创粉丝点击