Android Handler消息机制学习

栏目: 后端 · 发布时间: 5年前

内容简介:该类实现了Parcelable接口,你可以把它看作一个数据类

  Handler允许你发送和处理Message,以及和线程相关联的Runnable对象。每一个Handler实例都与一个线程及该线程的MessageQueue相关联。既当你创建一个Handler时,该Handler必须绑定一个线程以及该线程的消息队列,一旦它被创建,它能把messages和runnables传送到message queue,并在它们从message queue中出来的时候执行它们。

  Handler主要有两个主要用途:

  • 在未来的某个时间点调度messages和runnables的执行
  • 将要在不同线程上执行的操作加入队列

当你的应用程序被创建出来的时候,主线程会专门运行一个message queue来管理最顶级的应用对象(如activities, broadcast receivers,等等)以及它们创建的任何其它窗口。你可以创建你自己的线程,通过Handler来与主线程建立联系

2.源码分析

2.1 MessageQueue-消息队列

  MessageQueue是一个通过Looper分发它持有的消息列表的低层级类。Messages没有直接添加到MessageQueue中,而是通过与Looper相关联的Handler对象。

  • Message-消息

该类实现了Parcelable接口,你可以把它看作一个数据类

**
 *
 * Defines a message containing a description and arbitrary data object that can be
 * sent to a {@link Handler}.  This object contains two extra int fields and an
 * extra object field that allow you to not do allocations in many cases.
 * 定义包含描述和任意数据对象的消息
 * 发送到Handler。这个对象包含两个额外的int字段和一个
 * 额外的对象字段,允许您在很多情况下不进行分配。
 * <p class="note">While the constructor of Message is public, the best way to get
 * one of these is to call {@link #obtain Message.obtain()} or one of the
 * {@link Handler#obtainMessage Handler.obtainMessage()} methods, which will pull
 * them from a pool of recycled objects.</p>
 * 注意:不要直接使用New Message()创建Message对象,最好的方式是通过Handler.obtainMessage()
 * 方法,它会从对象回收池中拉取该消息对象
 */
public final class Message implements Parcelable {
    /** @hide */
    public static final Object sPoolSync = new Object();
    /**
     * Return a new Message instance from the global pool. Allows us to
     * avoid allocating new objects in many cases.
     * 从全局池返回一个新的消息实例。让我们在很多情况下避免分配新对象。
     */
    public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }
    **
     * Same as {@link #obtain()}, but sets the value for the target member on the  Message returned.
     * 与obtain()相同,但在返回的消息上设置目标成员的值。
     * @return A Message object from the global pool.
     * 返回来自全局池的消息对象
     */
    public static Message obtain(Handler h) {
        Message m = obtain();
        m.target = h;//接收传递过来的Handler

        return m;
    }
}
复制代码

2.2 Looper-消息轮询器

  Looper用于为线程轮询messages。线程默认是没有与之相关联的Lopper,我们必须通过Looper.prepare()方法去创建它。示例:

class LooperThread extends Thread {
    public Handler mHandler;

    public void run() {
        Looper.prepare();

        mHandler = new Handler() {
            public void handleMessage(Message msg) {
                // process incoming messages here
          }
        };

       Looper.loop();
    }
}
复制代码
  • ThreadLocal提供线程的局部变量,通过它访问线程独立初始化变量的副本。即Looper通过ThreadLocal类来与当前线程进行交互
//私用构造方法
//quitAllowed是否允许退出
private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);//实例化消息队列
    mThread = Thread.currentThread();//获取当前线程
}

/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
* 初始化当前线程的Looper
* 在它准备轮询之前,给你一个时机点去创建一个Handler并引用它
* 调用该方法后一定记得Looper.loop()方法,并结束的时候调用Looper.quit()方法退出
*/
public static void prepare() {
    prepare(true);
}

// sThreadLocal.get() will return null unless you have called prepare().
//必须先调用Looper.prepare()方法,否则返回空
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

private static void prepare(boolean quitAllowed) {
    //每一个线程只能有唯一的一个looper
    if (sThreadLocal.get() != null) {//不为空抛出异常
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));//设置Looper
}

/**
 * Return the Looper object associated with the current thread.  Returns
 * null if the calling thread is not associated with a Looper.
 * 返回与当前线程关联的looper
 */
public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

/**
 * Run the message queue in this thread. Be sure to call
 * {@link #quit()} to end the loop.
 * 在当前线程运行消息队友
 */
public static void loop() {
    final Looper me = myLooper();//获取looper
    if (me == null) {//为空则抛出异常
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;//获取looper的消息队列

    // Make sure the identity of this thread is that of the local process,
    // and keep track of what that identity token actually is.
    //确保这个线程的标识是本地进程的标识,
    //并跟踪身份令牌的实际情况。
    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();

    // Allow overriding a threshold with a system prop. e.g.
    // adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
    final int thresholdOverride =
            SystemProperties.getInt("log.looper."
                    + Process.myUid() + "."
                    + Thread.currentThread().getName()
                    + ".slow", 0);

    boolean slowDeliveryDetected = false;

    for (;;) {//无限轮询
        Message msg = queue.next(); // might block
        if (msg == null) { //没有message则不往下执行
            // No message indicates that the message queue is quitting.
            return;
        }

        ***省略代码***
        
        final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
        final long dispatchEnd;
        try {
            msg.target.dispatchMessage(msg);//调用Handler的dispatchMessage(msg)方法
            dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
        } finally {
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }
        //回收可能正在使用的消息。
        //在处理消息队列时,MessageQueue和Looper在内部使用。
        msg.recycleUnchecked();
    }
}

//sThreadLocal.get()
public T get() {
    Thread t = Thread.currentThread();//通过Thread的静态方法获取当前的线程
    //ThreadLocalMap是一个定制的HashMap(),仅适用于维护线程局部值,每一个线程都持有一个ThreadLocalMap对象
    ThreadLocalMap map = getMap(t);//传入当前线程获取当前线程的ThreadLocalMap对象
-------------------------------------------------------------------------------—————————————
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
-------------------------------------------------------------------------------—————————————
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}
复制代码

2.3 Handler

2.3.1 创建Handler对象

/**
 * Callback interface you can use when instantiating a Handler to avoid
 * having to implement your own subclass of Handler.
 * 如果你不想通过继承Handler来实现,你必须实现Callback接口
 */
public interface Callback {
    /**
     * @param msg A {@link android.os.Message Message} object
     * @return True if no further handling is desired
     */
    public boolean handleMessage(Message msg);
}
//默认构成器
//如果该Handler所绑定的线程没有looper,它将收不到任何messages,并且会抛出异常
public Handler() {
    this(null, false);
}
//默认构造器的Callback为空,所以当我们通过new Handler()来创建实例时,
//我们必须重写Handler的handleMessage(Message msg)方法,即:
companion object {//注意写成静态内部类的形式,避免内存泄漏
    private class MyHandler :Handler(){
        override fun handleMessage(msg: Message?) {
            super.handleMessage(msg)
        }
    }
}
-------------------------------------------------------------------------------—————————————
//主动实现Callback接口,来创建Handler实例
public Handler(Callback callback) {
    this(callback, false);
}
 companion object {
    private val mHandler1:Handler = Handler(object :Handler.Callback{
        override fun handleMessage(msg: Message?): Boolean {
            return true
        }
    })
    或
    private val mHandler2:Handler = Handler(Handler.Callback {
        true
    })

}
-------------------------------------------------------------------------------—————————————
 /**
 * Use the provided {@link Looper} instead of the default one.
 *
 * @param looper The looper, must not be null.
 * //不使用默认的looper
 */
public Handler(Looper looper) {
    this(looper, null, false);
}
//之前我看到某些前辈是通过下面这种方式来创建Handler实例,通过传递主线程的looper
//但这是没必要的,Handler默认就是使用主线程的looper(下面会分析)
//并且源码注释也说了,使用你自己的提供的looper而不是默认的
private val mHandler:Handler = object :Handler(Looper.getMainLooper()){
    override fun handleMessage(msg: Message?) {
        super.handleMessage(msg)
    }
}
-------------------------------------------------------------------------------—————————————
//该构造同上,如果你不想重写handleMessage(msg: Message?)方法,那么你就重写Callback接口
public Handler(Looper looper, Callback callback) {
    this(looper, callback, false);
}
//是否需要异步处理messages,默认是异步的
public Handler(boolean async) {
    this(null, async);
}
//自己提供looper,实现Callback接口,决定是否异步
public Handler(Looper looper, Callback callback, boolean async) {
    mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

-------------------------------------------------------------------------------—————————————
/*
 * Set this flag to true to detect anonymous, local or member classes
 * that extend this Handler class and that are not static. These kind
 * of classes can potentially create leaks.
 * 将此标志设置为true以检测匿名类、本地类或成员类
 * 继承了Handler不是静态的,可能存在内存泄漏
 */
private static final boolean FIND_POTENTIAL_LEAKS = false;

//通过Handler()、Handler(Callback callback)、Handler(boolean async)
//都会调用该构造器
public Handler(Callback callback, boolean async) {
    
    if (FIND_POTENTIAL_LEAKS) {//检查可能存在的内存泄漏,默认是false
        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 " + Thread.currentThread()
                    + " that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;//获取Looper中的消息队列
    mCallback = callback;
    mAsynchronous = async;
}
private static void handleCallback(Message message) {
    message.callback.run();//执行Message持有的Runnable
}
/**
 * Handle system messages here.
 * 处理系统Messages
 */
public void dispatchMessage(Message msg) {
    if (msg.callback != null) {//如果Message的Runnable不为空
        handleCallback(msg);调用Handler的handleMessage(msg)方法处理Message
    } else {
        if (mCallback != null) {//如果Handler的Callback不为空
            if (mCallback.handleMessage(msg)) {//调用Callback的handleMessage(msg)方法
                return;
            }
        }
        //否则调用Handler的handleMessage(msg)方法
        handleMessage(msg);
    }
}
复制代码

2.3.2 创建Message对象

public final Message obtainMessage()
{
    return Message.obtain(this);
}
public final Message obtainMessage(int what)
{
    return Message.obtain(this, what);
}
public final Message obtainMessage(int what, Object obj)
{
    return Message.obtain(this, what, obj);
}
public final Message obtainMessage(int what, int arg1, int arg2)
{
    return Message.obtain(this, what, arg1, arg2);
}
public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
{
    return Message.obtain(this, what, arg1, arg2, obj);
}
复制代码

2.3.3 发送Message

/**
 * Causes the Runnable r to be added to the message queue.
 * The runnable will be run on the thread to which this handler is 
 * attached. 
 * 将Runnable添加到消息队列中。
 * runnable将在此Handler所在的线程上运行。
 * 
 * @return Returns true if the Runnable was successfully placed in to the 
 *         message queue.  Returns false on failure, usually because the
 *         looper processing the message queue is exiting.
 * Runnable成功添加到消息队列中返回ture,失败返回false
 */
public final boolean post(Runnable r)
{
   return  sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
    Message m = Message.obtain();创建Message对象
    m.callback = r;把Runnale传递给Message
    return m;
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
    if (delayMillis < 0) {//延迟时间小于0,则置为0
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
//延迟发送
public final boolean postDelayed(Runnable r, long delayMillis)
{
    return sendMessageDelayed(getPostMessage(r), delayMillis);
}

public final boolean postDelayed(Runnable r, Object token, long delayMillis)
{
    return sendMessageDelayed(getPostMessage(r, token), delayMillis);
}

public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

 public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
    MessageQueue queue = mQueue;
    if (queue == null) {
        RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
        Log.w("Looper", e.getMessage(), e);
        return false;
    }
    return enqueueMessage(queue, msg, uptimeMillis);
}

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this;//把当前的Handler传递给Message的Handler
    if (mAsynchronous) {//是否异步
        msg.setAsynchronous(true);
    }
    //最终调用MessageQueue的enqueueMessage方法
    return queue.enqueueMessage(msg, uptimeMillis);
}
MessageQueue:
boolean enqueueMessage(Message msg, long when) {
    if (msg.target == null) {//Message的Handler为空,抛出异常
        throw new IllegalArgumentException("Message must have a target.");
    }
    if (msg.isInUse()) {//Message正在使用,抛出异常
        throw new IllegalStateException(msg + " This message is already in use.");
    }

    synchronized (this) {
        if (mQuitting) {//判断是否退出
            IllegalStateException e = new IllegalStateException(
                    msg.target + " sending message to a Handler on a dead thread");
            Log.w(TAG, e.getMessage(), e);
            msg.recycle();//回收Message
            return false;
        }

        msg.markInUse();设置Message是否正在使用的Flag
        msg.when = when;
        Message p = mMessages;
        boolean needWake;//是否需要唤醒
        if (p == null || when == 0 || when < p.when) {
            // New head, wake up the event queue if blocked.
            msg.next = p;
            mMessages = msg;
            needWake = mBlocked;
        } else {
            // Inserted within the middle of the queue.  Usually we don't have to wake
            // up the event queue unless there is a barrier at the head of the queue
            // and the message is the earliest asynchronous message in the queue.
            //插入到队列的中间。通常我们不需要唤醒
            //启动消息队列,除非队列头部有阻碍
            //消息是队列中最早的异步消息。
            needWake = mBlocked && p.target == null && msg.isAsynchronous();
            Message prev;
            for (;;) {//开启无限轮询
                prev = p;
                p = p.next;
                if (p == null || when < p.when) {
                    break;
                }
                if (needWake && p.isAsynchronous()) {
                    needWake = false;
                }
            }
            msg.next = p; // invariant: p == prev.next
            prev.next = msg;
        }

        // We can assume mPtr != 0 because mQuitting is false.
        if (needWake) {
            nativeWake(mPtr);
        }
    }
    return true;
}
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

大学程序设计课程与竞赛训练教材

大学程序设计课程与竞赛训练教材

吴永辉、王建德 / 机械工业出版社 / 2013-6 / 69.00

本书每章为一个主题,实验内容安排紧扣大学算法和数学的教学,用程序设计竞赛中的算法和数学试题作为实验试题,将算法和数学的教学与程序设计竞赛的解题训练结合在一起;在思维方式和解题策略的训练方面,以问题驱动和启发式引导为主要方式,培养读者通过编程解决问题的能力。 本书特点: 书中给出的234道试题全部精选自ACM国际大学生程序设计竞赛的世界总决赛以及各大洲赛区现场赛和网络预赛、大学程序设计竞......一起来看看 《大学程序设计课程与竞赛训练教材》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试