首先看一下handler发送和接收数据的代码
private var mHandler = Handler {
print(it.toString())
false
}
private fun sendMessage() {
Thread {
mHandler.sendMessage(Message.obtain().apply {
what = 0
arg1 = 1
arg2 = 2
obj = "obj"
})
}.start()
}
handler.sendMessage 调用的是 MessageQueue.enqueueMessage
handler的Callback 是looper的dispatchMessage,其中message获取是通过MessageQueue.next
Handler
初始化
public Handler(@Nullable Callback callback) {
this(callback, false);
}
public interface Callback {
boolean handleMessage(@NonNull Message msg);
}
消息分发机制,再Looper中调用,为了接收数据
/**
* Handle system messages here.
*/
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
消息发送
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
实际上调用下面的方法
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);
}
实际上调用MessageQueue的enqueueMessage方法,传递了消息和时间
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);
}
Message
public final class Message implements Parcelable
一个序列化的数据。
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();
}
要注意的是,新建Message的时候,使用obtain()方法,因为这样会使用Message的一个缓存。(性能优化)
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = UID_NONE;
workSourceUid = UID_NONE;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
消息回收的方法。
MessageQueue
数据入队列的方法,并且再这里控制线程的唤醒,此队列为优先级队列
boolean enqueueMessage(Message msg, long when) {
//加锁操作
synchronized (this) {
//判断是否要唤醒线程
//消息队列中的链表的头部元素为null;立即执行;msg的执行时间早与链表中的头部元素的时间。这三个判断都要把msg设置成消息队列中链表的头部是元素
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
//唤醒状态判断
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
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; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
}
获取数据的方法,Looper中调用
Message next() {
//控制退出的方法
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
//死循环
for (;;) {
//线程挂起,根据下一个要获取message的时间
nativePollOnce(ptr, nextPollTimeoutMillis);
//同步锁
synchronized (this) {
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
// If first time idle, then get the number of idlers to run.
// Idle handles only run if the queue is empty or if the first message
// in the queue (possibly a barrier) is due to be handled in the future.
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
//注意这个循环继续,pendingIdleHandlerCount 很少大于0,所以很少会走到下面
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
}
}
Looper
Looper的初始化
/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*/
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
//这里确定一个ThreadLocal只能和一个looper绑定
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
/**
* Initialize the current thread as a looper, marking it as an
* application's main looper. The main looper for your application
* is created by the Android environment, so you should never need
* to call this function yourself. See also: {@link #prepare()}
*/
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
这里说明开启一个handler需要一个looper,一个是子线程开启,一个是为了主线程开启。
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
私有的构造函数,必须通过方法初始化。新建了一个MessageQueue,获取当前线程。(不是单例模式,可以看成是线程里的单例,线程隔离)
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
通过ThreadLocal来实现线程隔离。注意这里使用的是static final
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
获取当前looper的代码,通过ThreadLocal获取,下面会讲解Looper的唯一性。
Looper的 loop()方法,主要是拿到Message和发送Message。
public static void loop() {
//获取当前looper
final Looper me = myLooper();
//获取MessageQueue
final MessageQueue queue = me.mQueue;
//一个死循环
for (;;) {
//获取消息,详见messageQueue
Message msg = queue.next(); // might block
//把数据发送出去
msg.target.dispatchMessage(msg);
//消息回收,内存优化
msg.recycleUnchecked();
}
}
ThreadLocal
首先看一下Thread源码,里面有ThreadLocal.ThreadLocalMap,ThreadLocal中有ThreadLocalMap,每一个线程都有自己的ThreadLocal。
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
下面看一下ThreadLocal.ThreadLocalMap的代码
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
/**
* The table, resized as necessary.
* table.length MUST always be a power of two.
*/
private Entry[] table;
}
实际保存的是一个数组,Entry是也Map,ThreadLocal<?>对应的是key,Object 对应所存储的值,
table的长度必须是二的倍数,因为第一位存放key,第二位存放value,以此类推。
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
这是ThreadLocal的set代码,可以看出,ThreadLocalMap实际上key是this,value就是传递过来的Looper对象。
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
这里的代码是获取Looper对象的代码。
Thread 对应了一个 static final ThreadLocal(唯一确定了)再创建Looper时,Looper唯一确定, Looper 通过prepare保证了ThreadLocal和Looper 唯一绑定,整个线程只有一个Looper。
通过get和set方法,就可以设置和获取当前线程的唯一looper了。