public static void main(String[] args) {
.... //創建Looper和MessageQueue對象,用於處理主線程的消息
Looper.prepareMainLooper();
//創建ActivityThread對象
//建立Binder通道 (創建新線程)
thread.attach(false); Looper.loop(); //消息循環運行
throw new RuntimeException("Main thread loop unexpectedly exited");
}
我們看looper.loop()的源碼
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static void loop() {
Looper me = myLooper();//獲取當前looper
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}//如果爲空,則拋異常
MessageQueue queue = me.mQueue;//把當前looper的queue賦值給局部變量queue
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();//確保當前線程屬於當前進程,並且記錄真實的token。
final long ident = Binder.clearCallingIdentity();
while (true) {
Message msg = queue.next(); // might block有可能會阻塞
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.退出消息的標示就是target爲空
return;
}
long wallStart = 0;
long threadStart = 0;
// This must be in a local variable, in case a UI event sets the logger 一個局部變量,爲ui事件設置log記錄。
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
wallStart = SystemClock.currentTimeMicro();
threadStart = SystemClock.currentThreadTimeMicro();
}
//handler處理消息
msg.target.dispatchMessage(msg);
if (logging != null) {
long wallTime = SystemClock.currentTimeMicro() - wallStart;
long threadTime = SystemClock.currentThreadTimeMicro() - threadStart;
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
if (logging instanceof Profiler) {
((Profiler) logging).profile(msg, wallStart, wallTime,
threadStart, threadTime);
}
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.確保調用過程中線程沒有被銷燬
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
//處理完成後,調用Message.recycle()將其放入Message Pool中。
msg.recycle();
}
}
}
那麼知乎上一個大神這麼說 隔開隔開
對於線程既然是一段可執行的代碼,當可執行代碼執行完成後,線程生命週期便該終止了,線程退出。而對於主線程,我們是絕不希望會被運行一段時間,自己就退出,那麼如何保證能一直存活呢?簡單做法就是可執行代碼是能一直執行下去的,死循環便能保證不會被退出,例如,binder線程也是採用死循環的方法,通過循環方式不同與Binder驅動進行讀寫操作,當然並非簡單地死循環,無消息時會休眠。但這裏可能又引發了另一個問題,既然是死循環又如何去處理其他事務呢?通過創建新線程的方式。
真正會卡死主線程的操作是在回調方法onCreate/onStart/onResume等操作時間過長,會導致掉幀,甚至發生ANR,looper.loop本身不會導致應用卡死。
作者:Gityuan
鏈接:https://www.zhihu.com/question/34652589/answer/90344494
來源:知乎
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
隔開隔開
這是一個大神說的 乍看起來好像有點不懂
那麼我來說說我的理解
Looper.loop()中的for循環會讓當前線程阻塞,不是卡死,這個和操作系統有關。如果你在主線程操作,如activity生命週期onCreate、主線程的handler,實際上是都是通過handler發消息的,消息會在剛纔的for循環中處理,這個消息會喚醒線程,如果你在onCreate(),onResume()裏面處理耗時操作,那麼下一次的比如用戶的點擊事件不能處理了,那就會卡死了