Android10 Framework—Handler消息系统—4.消息系统退出

36 阅读1分钟

十年鹅厂程序员,专注大前端、AI、个人成长

Android系列文章目录

UI线程创建Looper,prepare传入参数为false

public static void prepareMainLooper() {
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}

子线程创建Looper,prepare传入参数为true

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

这样很好理解,因为UI线程不允许消息系统退出,退出了APP就无法工作了;而子线程消息系统是可以退出的;可以调用Looper的如下方法退出

//非安全退出
public void quit()
//安全退出
public void quitSafely()

他们都会调用MessageQueue的quit方法

void quit(boolean safe) {
    if (!mQuitAllowed) {
        throw new IllegalStateException("Main thread not allowed to quit.");
    }

    synchronized (this) {
        if (mQuitting) {
            return;
        }
        mQuitting = true;

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

        // We can assume mPtr != 0 because mQuitting was previously false.
        nativeWake(mPtr);
    }
}

非安全退出会直接调用removeAllMessagesLocked,它将mMessages队列中所有消息都进行回收;

private void removeAllMessagesLocked() {
    Message p = mMessages;
    while (p != null) {
        Message n = p.next;
        p.recycleUnchecked();
        p = n;
    }
    mMessages = null;
}

安全退出会直接调用removeAllFutureMessagesLocked

private void removeAllFutureMessagesLocked() {
    final long now = SystemClock.uptimeMillis();
    Message p = mMessages;
    if (p != null) {
        if (p.when > now) {
            removeAllMessagesLocked();
        } else {
            Message n;
            //从队列中找到大于当前时间的第一个节点
            for (;;) {
                n = p.next;
                if (n == null) {
                    return;
                }
                if (n.when > now) {
                    break;
                }
                p = n;
            }
            p.next = null;
            //回收找到的节点开始后面所有节点
            do {
                p = n;
                n = p.next;
                p.recycleUnchecked();
            } while (n != null);
        }
    }
}

removeAllFutureMessagesLocked回收队列中所有大于当前时间的节点,其它节点依然会被分发;