Android Handler消息机制(5)MessageQueue和Handler

228 阅读2分钟

「这是我参与11月更文挑战的第19天,活动详情查看:2021最后一次更文挑战

Handler机制原理

3.MessageQueue之quit

quit 方法退出消息列表,通过参数 safe 决定是否直接退出

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

通过saft参数判断要移除的消息,removeAllFutureMessagesLocked()移除尚未处理的消息。

removeAllMessagesLocked移除所有的消息。

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

会根据当前消息的时间。判断他是否正在处理,等待消息处理完后再去删除所有的消息。

4.Handler

Handler是一个使用最频繁的类,主要用于消息的发送和处理。

先分析以下他的构造方法。

public Handler(@Nullable 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();
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread " + Thread.currentThread()
            + " that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}
​
@UnsupportedAppUsage
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
    mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

在初始化的过程中,首先会去获取当先线程的Looper实例mLooper,如果不存在则抛出异常。抛出的异常有些同学可能很眼熟,由这里可以知道,当我们在子线程使用Handler的时候要手动调用Looper.prepare()创建一个Looper对象,之所以主线程不用,是系统启动的时候帮我们自动调用了Looper.prepare()方法。 然后去关联Looper中的 MessageQueue 消息队列。

UI 线程在启动时会自动创建 Looper 实例,所以一般我们在 UI 线程中使用 Handler 时不需要传递 Looper 对象。而在子线程中则必须手动调用 Looper.prepare 和 Looper.loop 方法,并传递给 Handler ,否则无法使用。 在以前的文章中对这部分有介绍。

\