消息机制
- 概念
- ThreadLocal
- MessageQueue
- Looper
- Handler
- runOnUiThread()
概念
- MessageQueue:采用单链表的方法存储消息列表
- Looper:查询MessageQueue是否有新消息,有则处理,无则等待
- ThreadLocal:用于Handler获取当前线程的Looper
- 线程默认没有Looper,当使用Handler时需要手动创建,ActivityThread被创建时会初始化主线程的Looper,故主线程中默认可以使用Handler
ThreadLocal
ThreadLocal是线程内部数据存储类,通过它可以在指定线程中存储数据,且只能在该线程中访问,如在调用栈比较深时用于存储监听器,不需要全局变量即可实现监听线程的全部执行过程,且避免了监听器通过参数去传递
public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";private ThreadLocal<Boolean> mBooleanThreadLocal = new ThreadLocal<>();protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mBooleanThreadLocal.set(true);Log.d(TAG, "onCreate: Thread#main mBooleanThreadLocal = " + mBooleanThreadLocal.get());new Thread("Thread#1"){@Overridepublic void run() {mBooleanThreadLocal.set(false);Log.d(TAG, "onCreate: Thread#1 mBooleanThreadLocal = " + mBooleanThreadLocal.get());}}.start();new Thread("Thread#2"){@Overridepublic void run() {Log.d(TAG, "onCreate: Thread#2 mBooleanThreadLocal = " + mBooleanThreadLocal.get());}}.start();}
}
打印如下,虽然不同线程使用同一个ThreadLocal对象,但值却不一样
Thread#main mBooleanThreadLocal = true
Thread#1 mBooleanThreadLocal = false
Thread#2 mBooleanThreadLocal = null
其set()方法如下,内部通过所传入线程threadLocals(ThreadLocalMap.Entry)存储数据
public void set(T value) {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);
}ThreadLocalMap getMap(Thread t) {return t.threadLocals;
}void createMap(Thread t, T firstValue) {t.threadLocals = new ThreadLocalMap(this, firstValue);
}ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {table = new Entry[INITIAL_CAPACITY];int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);table[i] = new Entry(firstKey, firstValue);size = 1;setThreshold(INITIAL_CAPACITY);
}static class Entry extends WeakReference<ThreadLocal<?>> {Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value = v;}
}
再看下set()的实际实现
private void set(ThreadLocal<?> key, Object value) {Entry[] tab = table;int len = tab.length;int i = key.threadLocalHashCode & (len-1);for (Entry e = tab[i];e != null;e = tab[i = nextIndex(i, len)]) {ThreadLocal<?> k = e.get();if (k == key) {e.value = value;return;}if (k == null) {replaceStaleEntry(key, value, i);return;}}tab[i] = new Entry(key, value);int sz = ++size;if (!cleanSomeSlots(i, sz) && sz >= threshold)rehash();
}
其get()方法如下,若存在则返回数据,不存在则创建ThreadLocalMap,存储默认值null并返回
public T get() {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this);if (e != null) {T result = (T)e.value;return result;}}return setInitialValue();
}private T setInitialValue() {T value = initialValue();Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);return value;
}protected T initialValue() {return null;
}
MessageQueue
如下为插入操作enqueueMessage(),主要为链表的插入
boolean enqueueMessage(Message msg, long when) {......synchronized (this) {......msg.markInUse();msg.when = when;Message p = mMessages;boolean needWake;if (p == null || when == 0 || when < p.when) {msg.next = p;mMessages = msg;needWake = mBlocked;} else {needWake = mBlocked && p.target == null && msg.isAsynchronous();Message prev;for (;;) {prev = p;p = p.next;if (p == null || when < p.when) {break;}if (needWake && p.isAsynchronous()) {needWake = false;}}msg.next = p; prev.next = msg;}if (needWake) {nativeWake(mPtr);}}return true;
}
如下为读取操作,死循环遍历链表,在规定时间后将Message返回并从链表删除
Message next() {......for (; ; ) {......synchronized (this) {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;}} ......}......}
}
Looper
使用Handler需要Looper,否则会报错
可修改为如下
public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);new Thread("Thread#1") {@Overridepublic void run() {Looper.prepare();Looper looper = Looper.myLooper();Handler handler = new Handler();Looper.loop();}}.start();}
}
prepare()创建Looper(内部创建MessageQueue),并存储到ThreadLocal
public static void prepare() {prepare(true);
}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));
}private Looper(boolean quitAllowed) {mQueue = new MessageQueue(quitAllowed);mThread = Thread.currentThread();
}
loop()开启消息循环
- 死循环一直从MessageQueue的next()方法获取Message
- quit()、quitSafely()可让next()返回null退出Looper,前者直接退出,后者处理完MessageQueue中的已有消息后退出,退出后handler的send()返回false
- 调用Handler的dispatchMessage(),回到创建Handler所在的Looper中执行
public static void loop() {final Looper me = myLooper();......final MessageQueue queue = me.mQueue;for (;;) {Message msg = queue.next();if (msg == null) {return;}......try {msg.target.dispatchMessage(msg);......}......}
}
Handler
sendMessage()将Message插入到MessageQueue
public final boolean sendMessage(@NonNull Message msg) {return sendMessageDelayed(msg, 0);
}public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {if (delayMillis < 0) {delayMillis = 0;}return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {MessageQueue queue = mQueue;if (queue == null) {RuntimeException e = new RuntimeException(this + " sendMessageAtTime() called with no mQueue");Log.w("Looper", e.getMessage(), e);return false;}return enqueueMessage(queue, msg, uptimeMillis);
}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);
}
dispatchMessage()方法
- msg.callback即是传进来的Runnable,若不为空则调用其run()
- 判断mCallback是否为空,不为空调用其handleMessage(),当不想继承Handler创建子类时,其用于创建匿名内部类
- 否则调用子类的handleMessage()
public void dispatchMessage(@NonNull Message msg) {if (msg.callback != null) {handleCallback(msg);} else {if (mCallback != null) {if (mCallback.handleMessage(msg)) {return;}}handleMessage(msg);}}private static void handleCallback(Message message) {message.callback.run();}
runOnUiThread()
Activity中的runOnUiThread(),若当前线程是主线程,则直接执行,否则调用主线程创建的Handler中的post()
public final void runOnUiThread(Runnable action) {if (Thread.currentThread() != mUiThread) {mHandler.post(action);} else {action.run();}
}