Handler学习(未完)

Handler学习(未完)

2018, Jun 07    

Handler, MessageQueue, Looper
Handler:

  1. 外界通过handler发送Message,handler将Message放入MessageQueue中
  2. Handler收到looper调用处理Message的方法,根据消息内容做相应处理(dispatchMessage)。调用的位置决定了处理消息位于哪个线程。
    MessageQueue:
    存放Message的队列
    Looper:
    循环从MessageQueue中取出message,调用Message中的Target的diapatch方法实现消磁处理(即Handler)

    源码解析

    image

Message结构本身是一个数据链表。 Looper的作用就是从消息队列中取消息交给handler去处理。 looper是一个线程一个的,Looper类可以认为是一个单例模式,只不过有几点特殊:(1)不是传统的static持有自己对象,而额外加了ThreadLocal来标明是线程内独有的,因此looper的方法几乎都是public static修饰的。(2)创建looper不是在过去的时候,而是在prepare中,在获取的时候直接用当前ThreadLocal的get方法来返回 在创建looper的时候,会创建一个MessageQueue,取当前线程mThread,但是mThread不是决定looper执行位于哪个线程的因素。因为looper是线程持有的独立变量,所以不可能在当前线程中拿到别的线程的变量,(除了mainlooper,Looper中有一个非线程独立的全局变量来保存mainlooper,looper的初始化在activityThread中,决定了他是应用线程级别的looper,而且如果再别的地方再去用prepareMainLooper去小黄建mainlooper时,会因为已经创建过而报异常)。

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}

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

public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}
private static Looper sMainLooper;  // guarded by Looper.class
public static void prepareMainLooper() {
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}

loop方法的loop方法应该是决定handler处理消息的所在线程。但是因为loop对象本身就是属于所在线程的变量,因此loop的执行也只会在当前线程中(别的线程中不存在它),也就是创建Looper的地方。loop方法在最开始的时候会去获取一下当前线程looper,从这个looper中取queue,queue中的元素是message,handler又是message的成员变量,这样就决定了不管在那个线程给handler发送消息,都不会影响改变线程,因为handler只负责向在创建时已经决定好的特定线程的looper的queue中放入message。
如果在一个线程中创建,在另一个线程中调用loop,会直接报looper不存在异常,或就执行另一个线程的loop方法,而这个线程中的message不包含要用来处理消息的handler,handler对应的loop仍然不会开始执行,向handler中发送消息没有用。(虽然会去wake,不确定逻辑,到native方法层了) handler在创建的时候一定要有looper,即使不在创建的时候传入looper,默认的构造方法也要用Looper去获取当前线程的looper,因此除非是主线程,在创建的时候一定要prepare,否则会直接报异常。

public Handler(Callback callback, boolean async) {
        ...
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
    
public Handler(Looper looper, Callback callback, boolean async) {
    mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

向handler发送消息: 也就是向queue中存入message,等着looper取到执行。
handler处理消息: looper调用handler的diapatchMessage方法。处理的方式对应着创建handler时决定好的处理消息的方式。有三种: CallBack handler.post(new Runnable), 和 handler的handlemessage

  • handler.post(new Runnable)会取一个message然后将传入的runnalbe赋给meg的callback
  • CallBack会创建为Handler的私有变量Callback
  • handler的handlemessage是一个空方法
    三者执行的优先级为:优先执行msg的callback,如果为空;执行创建handler时的callback,最后调用handlerMessage方法。
public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}
public final boolean post(Runnable r) {
   return sendMessageDelayed(getPostMessage(r), 0);
}

private static Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;
    return m;
}

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

移除所有消息 removeMessages和removeCallbacksAndMessages都是用来移除消息的,移除特定消息或移除所有消息。 退出loop 退出loop有两个方法,调用loop的quit方法和quitSafe方法,区别就是safe方法等到队列中的任务执行完才退出。

if (safe) {
    removeAllFutureMessagesLocked();
} else {
    removeAllMessagesLocked();
}

* 循环* 整个过程中会涉及两个循环,一个是loop的循环,只要开启了会一直等待去处理消息,直到拿不到消息。一个是messagequeue中的next方法拿下一个消息,会一直循环知道拿到消息或者quit。

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;
            }
            ...
            try {
                msg.target.dispatchMessage(msg);
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            ...
        }
    }
Message next() {
...
        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;
        for (;;) {
            ...
            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                if (msg != null && msg.target == null) {                   
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                if (msg != null) {
                    if (now < msg.when) {
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    nextPollTimeoutMillis = -1;
                }
                if (mQuitting) {
                    dispose();
                    return null;
                }
                ...

            ...
         }
    }

** 注释
ThreadLocal是线程局部变量的类,为每个使用该变量的线程提供独立的变量副本。