《Android 开发艺术与探索》笔记——(10)Android 的消息机制

Android 消息机制主要是 Handler,Looper,MessageQueue 这三者。

其中 MessageQueue 是 Looper 内的对象,Looper 是 Handler 内的对象。

每一个线程拥有一个 Looper,一个 Looper 拥有一个消息队列。

消息机制用来在两个线程之间沟通,既然是沟通,那么就需要一个桥梁,Android 里这个桥梁就是 Handler。

线程共享之间共享的有堆、全局变量、静态变量等。

我们一般将 Handler 作为全局变量,那么两个线程都能够对它进行访问。

每个线程都会有一个 ThreaLocal.Values 对象,存放此线程所有的 ThreadLocal 的值,每个线程的 Looper 就存放在这里(有的话)。ThreadLocal.Values 内部实现是一个 Object 数组 table,每个ThreadLocal 通过 hash 生成下标,存放它的值。

这里写图片描述

调用 Looper.prepare() 方法时,就会为当前线程创建一个 Looper,即 Looper 的 TheadLocal< Looper >内部对象 sThreadLocal 以自己为 key 将自己包装的 Looper 放入当前线程的 ThreadLocal.Values。

比如主线程 ActivityThread 运行时,会调用 Looper.parpareMainLooper() (主线程特殊的 Looper.prepare()),此时 Looper 的内部对象 sThreadLocal 会以自己为 key 将自己包装的 Looper 存储在主线程的 ThreadLocal.Values 对象中。

//ActivityThread
Looper.prepareMainLooper(); // 会调用 Looper.prepare(false);

//Looper
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

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

//ThreadLocal
public void set(T value) {
    Thread currentThread = Thread.currentThread();
    Values values = values(currentThread);
    if (values == null) {
        values = initializeValues(currentThread);
    }
    values.put(this, value);
}

创建 Handler 时,Looper.myLooper() 方法会到当前线程的 TreadLocal 区域中寻找 Looper,即 sThreadLocal 到当前线程的 ThreadLocal.Values 中寻找以自己为 key 的值,找不到会报错,在主线程中,因为已经创建,一定找得到,找到 Looper,相应的消息队列也就找到了。

//Handler
mLooper = Looper.myLooper();

//Looper
public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

//ThreadLocal
public T get() {
    // Optimized for the fast path.
    Thread currentThread = Thread.currentThread();
    Values values = values(currentThread);
    if (values != null) {
        Object[] table = values.table;
        int index = hash & values.mask;
        if (this.reference == table[index]) {
            return (T) table[index + 1];
        }
    } else {
        values = initializeValues(currentThread);
    }

    return (T) values.getAfterMiss(this);
}

使用时,在子线程中利用 Handler.sendMessage() 发出消息,发出消息的动作会将消息存入 MessageQueue 中,Looper 时刻监督着 MessageQueue,这时它就会启动,将消息再传给Handler,Handler 来处理。

猜你喜欢

转载自blog.csdn.net/gdeer/article/details/52610276