handler 相关知识复习

handler创建过程

1.当我们创建一个handler时,会调用Looper.myLooper()threadlocal中获取一个looper对象(ThreadLocal的知识点 )

   mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;

这里如果获取不到looper对象会抛出异常,主线程(ActivityThread)已经为我们初始化了looper,如果在子线程创建handler则需要手动调用Looper.prepare()来初始化looper对象到ThreadLocal中,并且该方法同一个线程只能调用一次。

 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));
    }

2.子线程中创建handler

  • 在子线程中创建handler,在子线程中处理 messge
  thread {
            Looper.prepare()
            Handler {
                println(Thread.currentThread().name)
                true
            }.sendEmptyMessage(0)
            Looper.loop()
        }
  • 在子线程创建handler, 在主线程处理messge
      thread {
            val looper = Looper.getMainLooper()
            Handler(looper) {
                println(Thread.currentThread().name + "----$it")
                true
            }.apply {
                (0..10).forEach {
                    sendEmptyMessage(it)
                }
            }
        }
  • 使用HandlerThread,类似第一个
    /**
     * handler thread 在一个名为work的线程中顺序处理消息
     */
    fun test3(){
        val thread = HandlerThread("work").apply { start() }
        Handler(thread.looper){
            println(Thread.currentThread().name + "----${it.what}")
            true
        }.apply {
            (0..10).forEach {
                sendEmptyMessage(it)
            }
        }
    }

关于Looper

对一个handler来说looper对象是必不可少的

1.Looper是什么
按照习惯直接看源码注释

Class used to run a message loop for a thread. 用于为线程运行消息循环的类。

好了,我们来看一下Looper如何运行消息循环

2.构造方法

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

这里初始化了MessageQueue对象,习惯性看一下该类的注释

/**
 * Low-level class holding the list of messages to be dispatched by a
 * {@link Looper}.  Messages are not added directly to a MessageQueue,
 * but rather through {@link Handler} objects associated with the Looper.
 *
保存由{@link Looper}调度的消息列表。消息不是直接添加到MessageQueue,而是通过与Looper关联的{@link Handler}对象添加。

明白了就是用来保存消息的队列, 而消息是通过handler添加进来的

3.Looper 如何运行消息循环
接着翻源码,很快可以找到这个最长的方法体loop()方法

 /**
     * 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();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;
        ...
         for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
           ...
           msg.target.dispatchMessage(msg);
           ...
        }
    }

方法比较长,这里只看关键部分,方法内部有一个死循环不停的从MessageQueue对象中获取消息体,并且调用了message内不的target对象的dispatchMessage方法来处理消息。

    @UnsupportedAppUsage
    /*package*/ Handler target;

看一下target对象,得知最终会交给handler处理消息。

4.形成闭环
现在我们想知道handler是何时赋值到Message的target对象上的,通过上面对MessageQueue类的注释,Message是通过Handler添加到MessageQueue中的,可以联想到handler常用的sendMessage(@NonNull Message msg)方法

    /**
     * Pushes a message onto the end of the message queue after all pending messages
     * before the current time. It will be received in {@link #handleMessage},
     * in the thread attached to this handler.
     *  
     * @return Returns true if the message was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.
     */
    public final boolean sendMessage(@NonNull Message msg) {
        return sendMessageDelayed(msg, 0);
    }

继续看最终调用的方法

    private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
            long uptimeMillis) {
        msg.target = this;
        msg.workSourceUid = ThreadLocalWorkSource.getUid();

        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

找到了,handler在这里将当前对象赋值到target上,并且将message添加到MessageQueue 中。
通过分析looper这里同时得出handler的工作机制:

1.Handler初始化时需要获取当前线程的Looper对象,Looper对象创建时会同时创建MessageQueue对象。
2.Handler对象通过sendMessage方法生成Message对象(其中target为handler自身的引用),并且添加到Looper对象创建的MessageQueue中。
3.Looper对象会通过Loop方法运行消息循环,获取MessageQueue中的Message对象,然后调用target(handler)的dispatchMessage方法来处理消息。

扩展:深入理解MessageQueue

手打,如有错误或问题可留言:)

你可能感兴趣的:(handler 相关知识复习)