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类

扫描二维码关注公众号,回复: 14782051 查看本文章

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(); //回收处理过消息: 清理内部数据, 并添加为消息池的第一个消息

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

猜你喜欢

转载自blog.csdn.net/yuanzhihui123/article/details/50558367