
在Android開發(fā)中主線程扮演著至關(guān)重要的角色。毫不夸張的說它就相當(dāng)于Android的心臟。只要它還在跳動的運行Android應(yīng)用就不會終止。它負責(zé)處理UI事件、界面更新、以及與用戶交互的各種操作。本文將深入分析Android主線程的原理、獨特機制以及應(yīng)用為開發(fā)者提供全面的了解和掌握主線程的知識。主線程的原理Android應(yīng)用的核心原則之一是單線程模型也就是說大多數(shù)與用戶界面相關(guān)的操作都必須在主線程中執(zhí)行。這一原則的背后是Android操作系統(tǒng)的設(shè)計主要有以下幾個原因UI一致性在單線程模型下UI操作不會被多線程競爭導(dǎo)致的不一致性問題確保了用戶界面的穩(wěn)定性和一致性。性能優(yōu)化單線程模型簡化了線程管理降低了多線程帶來的復(fù)雜性有助于提高應(yīng)用性能。安全性通過將UI操作限制在主線程可以減少因多線程競爭而引發(fā)的潛在問題如死鎖和競爭條件。主線程的原理可以用以下偽代碼表示publicclassMainThread{publicstaticvoidmain(String[]args){// 初始化應(yīng)用Application appcreateApplication();// 創(chuàng)建主線程消息循環(huán)Looper.prepareMainLooper();// 啟動主線程while(true){Message msgLooper.getMainLooper().getNextMessage();if(msg!null){// 處理消息app.handleMessage(msg);}}}}在上述偽代碼中主線程通過消息循環(huán)Message Loop來不斷處理消息這些消息通常包括UI事件、定時任務(wù)等。應(yīng)用的UI操作都會被封裝成消息然后由主線程依次處理。主線程的獨特機制主線程有一些獨特的機制其中最重要的是消息隊列Message Queue和Handler。消息隊列Message Queue消息隊列是主線程用來存儲待處理消息的數(shù)據(jù)結(jié)構(gòu)。每個消息都有一個與之相關(guān)的Handler它負責(zé)將消息放入隊列中然后由主線程依次處理。消息隊列的機制確保了消息的有序性和及時性。publicMessagenext(){final long ptrmPtr;if(ptr0){returnnull;}int pendingIdleHandlerCount-1;int nextPollTimeoutMillis0;for(;;){if(nextPollTimeoutMillis!0){Binder.flushPendingCommands();}nativePollOnce(ptr,nextPollTimeoutMillis);synchronized(this){final long nowSystemClock.uptimeMillis();Message prevMsgnull;Message msgmMessages;if(msg!nullmsg.targetnull){do{prevMsgmsg;msgmsg.next;}while(msg!null!msg.isAsynchronous());}if(msg!null){if(nowmsg.when){nextPollTimeoutMillis(int)Math.min(msg.when-now,Integer.MAX_VALUE);}else{// Got a message.mBlockedfalse;if(prevMsg!null){prevMsg.nextmsg.next;}else{mMessagesmsg.next;}msg.nextnull;msg.markInUse();returnmsg;}}else{nextPollTimeoutMillis-1;}...}...}}HandlerHandler是一個與特定線程關(guān)聯(lián)的對象它可以用來發(fā)送和處理消息。在主線程中通常使用new Handler(Looper.getMainLooper())來創(chuàng)建一個與主線程關(guān)聯(lián)的Handler。開發(fā)者可以使用Handler來將任務(wù)提交到主線程的消息隊列中。Handler handlernewHandler(Looper.getMainLooper());handler.post(newRunnable(){Overridepublicvoidrun(){// 在主線程執(zhí)行}});同步屏障在Android中消息可以分為同步消息和異步消息。通常我們發(fā)送的消息都是同步消息。然而有一種特殊情況即開啟同步屏障。同步屏障是一種消息機制的特性可以阻止同步消息的處理只允許異步消息通過。通過調(diào)用MessageQueue的postSyncBarrier()方法可以開啟同步屏障。在開啟同步屏障后發(fā)送的這條消息它的target為null。privateintpostSyncBarrier(long when){synchronized(this){final int tokenmNextBarrierToken;final Message msgMessage.obtain();msg.markInUse();// 沒有設(shè)置targettarget為nullmsg.whenwhen;msg.arg1token;Message prevnull;Message pmMessages;if(when!0){while(p!nullp.whenwhen){prevp;pp.next;}}if(prev!null){// invariant: p prev.nextmsg.nextp;prev.nextmsg;}else{msg.nextp;mMessagesmsg;}returntoken;}}那么開啟同步屏障后所謂的異步消息又是如何被處理的呢我們又可以回到之前MessageQueue中的next方法了publicMessagenext(){// 省略部分代碼只體現(xiàn)出來同步屏障的代碼...for(;;){...synchronized(this){final long nowSystemClock.uptimeMillis();Message prevMsgnull;Message msgmMessages;//注意這里開始出來同步屏障//如果targetnull認為它就是屏障進行循環(huán)遍歷直到找到第一個異步的消息if(msg!nullmsg.targetnull){do{prevMsgmsg;msgmsg.next;}while(msg!null!msg.isAsynchronous());}...}...}}所以同步屏障是會讓消息順序進行調(diào)整讓其忽略現(xiàn)有的同步消息來直接處理臨近的異步消息?,F(xiàn)在聽起來已經(jīng)知道了同步屏障的作用但它的實際應(yīng)用又有哪些呢應(yīng)用場景雖然在日常應(yīng)用開發(fā)中同步屏障的使用頻率較低但在Android系統(tǒng)源碼中同步屏障的使用場景非常重要。一個典型的使用場景是在UI更新時例如在View的繪制、布局調(diào)整、刷新等操作中系統(tǒng)會開啟同步屏障以確保與UI相關(guān)的異步消息得到優(yōu)先處理。當(dāng)UI更新完成后同步屏障會被移除允許后續(xù)的同步消息得以處理。對應(yīng)的是ViewRootImpl#scheduleTraversals()voidscheduleTraversals(){if(!mTraversalScheduled){mTraversalScheduledtrue;// 設(shè)置同步屏障mTraversalBarriermHandler.getLooper().getQueue().postSyncBarrier();mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL,mTraversalRunnable,null);notifyRendererOfFramePending();pokeDrawLockIfNeeded();}}voidunscheduleTraversals(){if(mTraversalScheduled){mTraversalScheduledfalse;// 移除同步屏障mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);mChoreographer.removeCallbacks(Choreographer.CALLBACK_TRAVERSAL,mTraversalRunnable,null);}}經(jīng)典問題Android 主線程的消息循環(huán)是通過Looper和Handler來實現(xiàn)的。以下是一段偽代碼示例// 創(chuàng)建一個 Looper關(guān)聯(lián)當(dāng)前線程Looper.prepare();Looper loopLooper.myLooper();// 創(chuàng)建一個 Handler它將和當(dāng)前 Looper 關(guān)聯(lián)Handler handlernewHandler();// 進入消息循環(huán)Looper.loop();開啟loop后的核心代碼如下publicstaticvoidloop(){final Looper memyLooper();...for(;;){if(!loopOnce(me,ident,thresholdOverride)){return;}}}privatestaticbooleanloopOnce(final Looper me,final long ident,final int thresholdOverride){// 注意沒消息會被阻塞進入休眠狀態(tài)Message msgme.mQueue.next();// might blockif(msgnull){// No message indicates that the message queue is quitting.returnfalse;}...try{msg.target.dispatchMessage(msg);if(observer!null){observer.messageDispatched(token,msg);}dispatchEndneedEndTime?SystemClock.uptimeMillis():0;}catch(Exception exception){if(observer!null){observer.dispatchingThrewException(token,msg,exception);}throwexception;}finally{ThreadLocalWorkSource.restore(origWorkSource);if(traceTag!0){Trace.traceEnd(traceTag);}}...msg.recycleUnchecked();returntrue;}在這段示例中主線程的消息循環(huán)被啟動它會等待來自消息隊列的消息。有了這個基礎(chǔ)下面的問題就簡單了為什么主線程不會陷入無限循環(huán)主線程的消息循環(huán)不會陷入無限循環(huán)因為它不斷地從消息隊列中獲取消息并處理它們。如果沒有消息要處理消息循環(huán)會進入休眠狀態(tài)不會持續(xù)消耗 CPU 資源。只有在有新消息到達時主線程才會被喚醒來處理這些消息。這個機制確保主線程能夠響應(yīng)用戶的操作而不陷入死循環(huán)。如果沒有消息主線程會如何處理如果消息隊列為空主線程的消息循環(huán)會等待直到有新消息到達。在等待期間它不會執(zhí)行任何操作也不會陷入循環(huán)。這是因為 Android 的消息循環(huán)是基于事件驅(qū)動的只有當(dāng)有事件消息到達時才會觸發(fā)主線程執(zhí)行相應(yīng)的處理代碼。當(dāng)新消息被投遞到消息隊列后主線程會被喚醒執(zhí)行相應(yīng)的處理操作然后再次進入等待狀態(tài)。這種事件驅(qū)動的消息循環(huán)機制使得 Android 應(yīng)用能夠高效地管理用戶交互和異步操作同時保持了響應(yīng)性和低能耗。所以主線程不會陷入無限循環(huán)而是在需要處理事件時才會執(zhí)行相應(yīng)的代碼。結(jié)論Android主線程是應(yīng)用的核心負責(zé)處理UI事件、界面更新和定時任務(wù)等。了解主線程的原理和獨特機制是Android開發(fā)的關(guān)鍵它有助于確保應(yīng)用的穩(wěn)定性和性能。通過消息隊列和Handler開發(fā)者可以在主線程中安全地處理各種任務(wù)提供流暢的用戶體驗。最后大家分享一份全套的Android學(xué)習(xí)資料給那些想學(xué)習(xí) Android 的小伙伴們一點幫助適用于任何想學(xué)習(xí)Android開發(fā)但不知道從哪里開始的人也適用于已經(jīng)開始進行Android開發(fā)但想要變得更好的任何人一、Android所有方向的學(xué)習(xí)路線為了成為更好的 Android 開發(fā)者這里為大家提供了總的路線圖。它的用處就在于你可以按照上面的知識點去找對應(yīng)的學(xué)習(xí)資源保證自己學(xué)得較為全面。如果下面這個學(xué)習(xí)路線能幫助大家成為一個更好的 Android 開發(fā)者那么我的使命也就完成了包括Android應(yīng)用開發(fā)、系統(tǒng)開發(fā)、音視頻開發(fā)、Flutter開發(fā)、小程序開發(fā)、UI界面、車載系統(tǒng)開發(fā)等等二、學(xué)習(xí)軟件工欲善其事必先利其器。學(xué)習(xí)Android常用的Android Studio視頻教程和Android Studio最新的安裝包都在這里了給大家節(jié)省了很多時間。三、進階學(xué)習(xí)視頻我們在學(xué)習(xí)的時候往往書籍源碼難以理解閱讀困難這時候視頻教程教程是就很適合了生動形象加上案例實戰(zhàn)科學(xué)有趣才能更方便的學(xué)習(xí)下去。四、實戰(zhàn)案例光學(xué)理論是沒用的要學(xué)會跟著一起敲要動手實操才能將自己的所學(xué)運用到實際當(dāng)中去這時候可以搞點實戰(zhàn)案例來學(xué)習(xí)。五、經(jīng)典書籍閱讀閱讀Android經(jīng)典書籍可以幫助讀者提高技術(shù)水平開拓視野掌握核心技術(shù)提高解決問題的能力同時也可以借鑒他人的經(jīng)驗。對于想要深入學(xué)習(xí)Android開發(fā)的讀者來說閱讀Android經(jīng)典書籍是非常有必要的。六、面試資料我們學(xué)習(xí)Android必然是為了找到高薪的工作下面這些面試題是來自阿里、騰訊、字節(jié)等一線互聯(lián)網(wǎng)大廠最新的面試資料并且有阿里大佬給出了權(quán)威的解答刷完這一套面試資料相信大家都能找到滿意的工作。這份完整版的Android全套學(xué)習(xí)資料已經(jīng)上傳CSDN朋友們?nèi)绻枰梢晕⑿艗呙柘路紺SDN官方認證二維碼免費領(lǐng)取【保證100%免費】