Miss handler


//在native层,消息循环的休眠和唤醒使用了Linux内核的epoll机制和pipe
Looper.prepareMainLooper();//ActivityThread
public static void prepareMainLooper() {//不能退出消息队列,传递falseprepare(false);synchronized (Looper.class) {if (sMainLooper != null) {throw new IllegalStateException("The main Looper has already been prepared.");}sMainLooper = myLooper();}
}//ActivityThread
private static void prepare(boolean quitAllowed) {//不为空表示当前线程已经创建了Looperif (sThreadLocal.get() != null) {//每个线程只能创建一个Looper throw new RuntimeException("Only one Looper may be created per thread");}//创建Looper并设置给sThreadLocalsThreadLocal.set(new Looper(quitAllowed));
}//ActivityThread
private Looper(boolean quitAllowed) {//创建MessageQueuemQueue = new MessageQueue(quitAllowed);//绑定当前线程mThread = Thread.currentThread();
}//Looper
public static @Nullable Looper myLooper() {//获取Looperreturn sThreadLocal.get();
}/*
1.获取当前线程对应的Looper
2.获取对应的MessageQueue
3.拿到msg消息
4.msg消费
*///Looper
public static void loop() {//里面调用了sThreadLocal.get()获得刚才创建的Looper对象final Looper me = myLooper();if (me == null) {//如果Looper为空则会抛出异常throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");}final MessageQueue queue = me.mQueue;for (;;) {//这是一个死循环,从消息队列不断的取消息Message msg = queue.next(); // might blockif (msg == null) {//由于刚创建MessageQueue就开始轮询,队列里是没有消息的,等到Handler sendMessage enqueueMessage后队列里才有消息// No message indicates that the message queue is quitting.return;}//msg.target就是绑定的Handler,详见后面Message的部分,Handler开始msg.target.dispatchMessage(msg);msg.recycleUnchecked();}
}/*
在dispatchMessage方法中,message中callback是一个Runnable对象,如果callback不为空,则直接调用callback的run方法。
否则判断mCallback是否为空,mCallback在Handler构造方法中初始化,在主线程通过无参的构造方法,new出来的为null,所以会直接执行后面的handleMessage()方法。
*///handler
public void dispatchMessage(@NonNull Message msg) {//callback在message的构造方法中初始化或者使用 handler.post(Runnable)时候才不为空   if (msg.callback != null) {handleCallback(msg);} else {//mCallback是一个Callback对象,通过无参的构造方法创建出来的handler,该属性为null,此段不执行   if (mCallback != null) {if (mCallback.handleMessage(msg)) {return;}}handleMessage(msg);}
}/*创建Message 可以直接new Message 但是有更好的方式 Message.obtain。因为可以检查是否有可以复用的Message,避免过多的创建、销毁Message对象达到优化内存和性能的目地
*///Message
public static Message obtain(Handler h) {//调用重载的obtain方法Message m = obtain();//绑定创建Message对象的handlerm.target = h;return m;
}//Message
public static Message obtain() {//sPoolSync是一个Object对象,用来同步保证线程安全synchronized (sPoolSync) {//sPool是就是handler dispatchMessage 后,通过recycleUnchecked 回收用以复用的Message  if (sPool != null) {Message m = sPool;sPool = m.next;m.next = null;m.flags = 0; //清除正在使用标志sPoolSize--;return m;}}return new Message();
}/*
Handler发送消息,sendMessage(Message)调用sendMessageDelayed,继续调用sendMessageAtTime,继续调用enqueueMessage,继续调用messageQueue的enqueueMessage方法,将消息保存在了消息队列中,而最终由 Looper取出,交给Handler的dispatchMessage进行处理
*///handler
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {if (delayMillis < 0) {delayMillis = 0;}return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}//handler
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);
}/*
Message和Handler的绑定 
创建Message的时候可以通过 Message.obtain(Handler h) 这个构造方法绑定。
当然可以在Handler 中的 enqueueMessage()绑定了,所有发送Message的方法都会调用此方法入队,所以在创建Message的时候是可以不绑定的
*///handler
private boolean enqueueMessage(MessageQueue queue, Message msg,long uptimeMillis) {msg.target = this;msg.workSourceUid = ThreadLocalWorkSource.getUid();if (mAsynchronous) {msg.setAsynchronous(true);}return queue.enqueueMessage(msg, uptimeMillis);
}/*
Handler机制里面最主要的类MessageQueue,这个类就是所有消息的存储仓库,在这个仓库中,我们如何的管理好消息,这个就是一个关键点了。
消息管理就2点:
1)消息入库(enqueueMessage)
2)消息出库(next),所以这两个接口是确保线程安全的主要档口
*/
//MessageQueue
boolean enqueueMessage(Message msg, long when) {if (msg.target == null) {throw new IllegalArgumentException("Message must have a target.");}if (msg.isInUse()) {throw new IllegalStateException(msg + " This message is already in use.");}synchronized (this) {if (mQuitting) {IllegalStateException e = new IllegalStateException(msg.target + " sending message to a Handler on a dead thread");Log.w(TAG, e.getMessage(), e);msg.recycle();return false;}msg.markInUse();msg.when = when;Message p = mMessages;boolean needWake;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.nextprev.next = msg;}// We can assume mPtr != 0 because mQuitting is false.if (needWake) {nativeWake(mPtr);}}return true;
}//MessageQueue
Message next() {// 1.如果nextPollTimeoutMillis = -1,一直阻塞不会超时。    // 2.如果nextPollTimeoutMillis = 0,不会阻塞,立即返回。    // 3.如果nextPollTimeoutMillis > 0,最长阻塞nextPollTimeoutMillis毫秒(超时)//如果期间有程序唤醒会立即返回。 int nextPollTimeoutMillis = 0; for (;;) {//native的方法,在没有消息的时候回阻塞管道读取端,只有nativePollOnce返回之后才能往下执行//阻塞操作,等待nextPollTimeoutMillis时长nativePollOnce(ptr, nextPollTimeoutMillis);synchronized (this) {// Try to retrieve the next message.  Return if found.final long now = SystemClock.uptimeMillis();Message prevMsg = null;Message msg = mMessages;//如果target==null,那么它就是屏障,需要循环遍历,一直往后找到第一个异步的消息if (msg != null && msg.target == null) {// Stalled by a barrier.  Find the next asynchronous message in the queue.do {prevMsg = msg;msg = msg.next;} while (msg != null && !msg.isAsynchronous());}if (msg != null) {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;}} else {// No more messages.nextPollTimeoutMillis = -1;}}// Run the idle handlers.// We only ever reach this code block during the first iteration.for (int i = 0; i < pendingIdleHandlerCount; i++) {final IdleHandler idler = mPendingIdleHandlers[i];mPendingIdleHandlers[i] = null; // release the reference to the handlerboolean keep = false;try {keep = idler.queueIdle();} catch (Throwable t) {Log.wtf(TAG, "IdleHandler threw exception", t);}if (!keep) {synchronized (this) {mIdleHandlers.remove(idler);}}}// Reset the idle handler count to 0 so we do not run them again.pendingIdleHandlerCount = 0;// While calling an idle handler, a new message could have been delivered// so go back and look again for a pending message without waiting.nextPollTimeoutMillis = 0;}
}//handler
private static void handleCallback(Message message) {message.callback.run();
}/*
在handleMessage(Message)方法中,我们可以拿到message对象,根据不同的需求进行处理,整个Handler机制的流程就结束了
*//*
next函数:从线程里面取消息,而且每次都是队列的头部取,那么它加锁是不是没有意义呢?答案是否定的,我们必须要在next里面加锁,由于synchronized(this)作用范围是所有 this正在访问的代码块都会有保护作用,它可以保证 next函数和 enqueueMessage函数能够实现互斥。这样才能真正的保证多线程访问的时候MessageQueue 的有序进行。 
*//*
postSyncBarrier()
同步屏障:阻碍同步消息,只让异步消息通过。
*///MessageQueue
private int postSyncBarrier(long when) {// Enqueue a new sync barrier token.// We don't need to wake the queue because the purpose of a barrier is to stall it.synchronized (this) {final int token = mNextBarrierToken++;//从消息池中获取Messagefinal Message msg = Message.obtain();msg.markInUse();//初始化Message对象的时候,并没有给target赋值,因此 target==nullmsg.when = when;msg.arg1 = token;Message prev = null;Message p = mMessages;if (when != 0) {while (p != null && p.when <= when) {prev = p;p = p.next;}}if (prev != null) { // invariant: p == prev.nextmsg.next = p;prev.next = msg;} else {msg.next = p;mMessages = msg;}return token;}
}/*
Message 对象初始化的时候并没有给 target 赋值,因此,target == null 的来源就找到了。上面消息的插入也做了相应的注释。
target == null 的消息就进入了消息队列
*//*
当消息队列开启同步屏障的时候(即标识为 msg.target == null),消息机制在处理消息的时候,优先处理异步消息。
这样,同步屏障就起到了一种过滤和优先级的作用
*///Looper
public void quit() {mQueue.quit(false);
}//Looper
public void quitSafely() {mQueue.quit(true);
}/*
这两个函数是调用的MessageQueue的quit()。
*///MessageQueue
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();}//native的方法,在没有消息的时候回阻塞管道读取端,只有nativePollOnce返回之后才能往下执行//阻塞操作,等待nextPollTimeoutMillis时长//通过向管道mWakeEventFd写入值来标志唤醒信号// We can assume mPtr != 0 because mQuitting was previously false.nativeWake(mPtr);}
}/*
remove消息,释放内存
*/
//MessageQueue
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);}}
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部