关于Android中的Handler 机制

概述

在开发中,Handler通常用于异步消息处理,相关联的类有:

ThreadLocal、Looper、MessageQueue、Message、Handler.

Handler持有MessageQueue和Looper,而Looper维护着一个MessageQueue,Message中包含Handler和Runnable成员变量和CallBack等。

其中

  • ThreadLocal是把新创建的Looper对象设置进线程本地存储区里。
  • Looper在后台不断轮询获取Message,后调用msg.target.dispatchMessage()执行,这个target即是我们的Handler。
  • MessageQueue是一个连表结构的集合。里面装有多个Runnable、Message对象
  • Message类似一个JavaBean,其中包含了消息ID,消息处理对象CallBack以及处理的数据Message.obj等
  • Handler是一个调度器,发送消息会调用enqueueMessage方法将消息打入MessageQueue。

在一个线程中通过调用Looper.prepare();初始化即可使线程成为Looper线程;通过enqueueMessage来发送消息;并通过Looper.loop() 来循环处理消息队列

ThreadLocal

参考资料:解密ThreadLocal
正确理解ThreadLocal

ThreadLocal提供了线程局部变量,在线程的生命周期内起作用,使得各线程能够保持各自独立的一个对象,在Thread中将new出来的对象通过ThreadLocal.set()来设置独立于其他线程的对象,其他线程不可访问,不是用来解决线程同步问题的。

每个线程中都有一个ThreadLocalMap类对象,而ThreadLocal实例就是key,value是真正需要存储的Object,在Android’Handler机制中是使用当前Thread作为Key,Looper作为Value。

Looper.prepare

通过Looper.prepare();来初始化Looper,并将Looper对象存储到本地线程中,而后创建Handler对象,并掉用Looper.loop()方法进行轮询。

注意:一个线程可以有多个Handler,每个线程中只有一个Looper对象。

public static void prepare() 
{
    prepare(true);
}

private static void prepare(boolean quitAllowed) 
{
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));  // 创建Looper对象,并设置进TLS
}
//.....

Looper

private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

Looper初始化的时候会创建一个MessageQueue。

Looper.loop

public static final void loop() {
        Looper me = myLooper();  //得到当前线程Looper
        MessageQueue queue = me.mQueue;  //得到当前looper的MQ

        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();
        // 开始循环
        while (true) {
            Message msg = queue.next(); // 取出message
            if (msg != null) {
                if (msg.target == null) {
                    // message没有target为结束信号,退出循环
                    return;
                }
            //...
                // 将真正的处理工作交给message的target,即发送消息的handler
                msg.target.dispatchMessage(msg);

Handler

首先,来看一下handler 的构造函数,

public Handler(Callback callback, boolean async) {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }

        mLooper = Looper.myLooper();// 设置looper
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue; //设置MessageQueue
        mCallback = callback; //设置CallBack
        mAsynchronous = async;
    }

Handler对象在构造时,不但会把Looper对象记录在它内部的mLooper成员变量中,还会把Looper对象的消息队列也一并记录

 public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

handler中的post 和send方法都会最终调用sendMessageAtTime方法,通过enqueueMessage方法将消息压入MessageQueue中

 public boolean sendMessageAtTime(Message msg, long uptimeMillis)
    {
        boolean sent = false;
        MessageQueue queue = mQueue;
        if (queue != null) {
            msg.target = this;  // message的target必须设为该handler!
            sent = queue.enqueueMessage(msg, uptimeMillis);
        }
        else {
            RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
        }
        return sent;
    }

Handler.dispatchMessage

这个方法是有Looper.loop()方法调用。

 public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            // 如果message设置了callback,即runnable消息,处理callback!
            handleCallback(msg);
        } else {
            // 如果handler本身设置了callback,则执行callback
            if (mCallback != null) {
                 /* 让activity等来实现Handler.Callback接口,避免了自己编写handler重写handleMessage方法。*/
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            // 如果message没有callback,则调用handler的钩子方法handleMessage
            handleMessage(msg);
        }
    }

    // 处理runnable消息
    private final void handleCallback(Message message) {
        message.callback.run();  //回调CallBack中的run方法!
    }
    // new Handler的时候需要实现的方法
    public void handleMessage(Message msg) {
    }

参考文章:
深入理解Handler机制
Android 事件机制详解
Android Handler消息机制的理解
android的消息处理机制(图+源码分析)——Looper,Handler,Message
解密ThreadLocal
正确理解ThreadLocal

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值