引言:
? ? ? ? 上篇文章分析了Activity.setContentView()方法,提到了Activity通過Window,也就是PhoneWindow.setContentView()將DecorView初始化,并將我們寫的layout裝載到DecorView的過程。View的繪制流程(一):Activity.setContentView()背后發生了什么,在setContentView()方法,只是將布局裝載進來,但是還并沒有將布局繪制顯示出來。這期,我們就從ActivityThread這個類開始。
?源碼分析:
? ? ? ? 因目前對startActivity()和Launch啟動Activity的流程尚不熟悉,就從緊挨著Activity生命周期的ActivityThread這個類開始著手。我們來看ActivityThread.handleResumeActivity()方法。
performResumeActivity方法中,調用了ActivityClientRecord.activity.performResume()方法,ActivityClientRecord.activity實際就是我們的Activity。我們來到Activity.performResume()方法。
這樣,我們的Activity就走到了生命周期的onResume()方法。接下來我們繼續回到ActivtiyThread.handleResumeActivity()方法往下看。
在這段代碼里,我們看到r.window = r.activity.getWindow()獲取的實際就是PhoneWindow,View deocr = r.window.getDecorView()獲取的就是在setContentView()方法中裝載了layout的DecorView,接下來我們看wm.addView(decor,l)方法。點addView()可以看到,addView()是ViewManager接口的的一個接口方法。這樣我們就找ViewManager接口的實現類,這樣我們就需要看下wm的賦值過程。在上面我們可以看到ViewManager wm = a.getWindowManager();wm通過activity.getWindowManager()方法賦值。可以看到這個wm是Activity中的mWindowManager,接下來我們看mWindowManager的賦值過程,可以看到mWindowManager =mWindow.getWindowManager(),mWindow就是Window。
所以在這里的wm的實現類就是WindowManagerImpl,所以看它的addView方法。
WindowManager.addView實際是調用了WindowManagerGlobal.addView()方法。
在ViewRootImpl.setView()方法中調用了requestLayout()方法。
在ViewRootImpl.requestLayout()中,調用了CheckThread()方法。
mThread是在ViewRootimpl構造方法中賦值,所以只要請求了ViewRootImpl.requestLayout()都會檢查當前線程是不是等于ViewRootImpl初始化時的線程,而ViewRootImpl是在主線程中初始化。我們更新UI時需要經過requestLayout()方法。所以,這就是為什么在子線程中更新UI會報錯的原因。我們繼續往下看。
performTraversals()中調用了三個重要方法performMeasure()、performLayout()、performDraw()方法。這三個方法分別是遍歷布局進行測量,布局,繪制的方法,我們的布局就可以顯示出來。這樣,我們從Activity生命周期到View的顯示過程就已經走完了。