文章目錄
- Android setContentView()源碼分析
- 前提
- setContentView() 源碼分析
- 總結
Android setContentView()源碼分析
前提
Activity 的生命周期與 ActivityThread 相關,調用 startActivity() 時,會調用 ActivityThread#performLaunchActivity(),接著調用 Activity#attach() 并在其中創建 PhoneWindow。
Activity 持有 PhoneWindow 對象,PhoneWindow 持有 DecorView。
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window, r.activityConfigCallback,r.assistToken, r.shareableActivityToken);return activity;
}
public class Activity {private Window mWindow;final void attach(Context context, ActivityThread aThread,Instrumentation instr, IBinder token, int ident,Application application, Intent intent, ActivityInfo info,CharSequence title, Activity parent, String id,NonConfigurationInstances lastNonConfigurationInstances,Configuration config, String referrer, IVoiceInteractor voiceInteractor,Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,IBinder shareableActivityToken) {// 創建PhoneWindowmWindow = new PhoneWindow(this, window, activityConfigCallback);}
}
public class PhoneWindow extends Window {private DecorView mDecor;ViewGroup mContentParent;
}
setContentView() 源碼分析
// Activity#setContentView()
public void setContentView()(@LayoutRes int layoutResID) {// 調用PhoneWindow#setContentView()getWindow().setContentView(layoutResID);initWindowDecorActionBar();
}public Window getWindow() {return mWindow;
}
// PhoneWindow#setContentView()
// 核心代碼:
public void setContentView()(int layoutResID) {if (mContentParent == null) {// 初始化DecorViewinstallDecor();} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {mContentParent.removeAllViews();}// 將布局添加到ContentView中mLayoutInflater.inflate(layoutResID, mContentParent);
}
// PhoneWindow#installDecor()
private void installDecor() {mForceDecorInstall = false;if (mDecor == null) {// 創建DecorViewmDecor = generateDecor(-1);} else {mDecor.setWindow(this);}if (mContentParent == null) {// 獲取ContentViewmContentParent = generateLayout(mDecor);}
}
// PhoneWindow#generateDecor()
protected DecorView generateDecor(int featureId) {Context context;if (mUseDecorContext) {Context applicationContext = getContext().getApplicationContext();if (applicationContext == null) {context = getContext();} else {context = new DecorContext(applicationContext, this);if (mTheme != -1) {context.setTheme(mTheme);}}} else {context = getContext();}// 創建DecorView,DecorView繼承自FrameLayoutreturn new DecorView(context, featureId, this, getAttributes());
}
// PhoneWindow#generateLayout()
// 核心代碼:
protected ViewGroup generateLayout(DecorView decor) {// 布局idint layoutResource;int features = getLocalFeatures();// 省略layoutResource賦值流程,根據主題賦值// ...// 加載layoutResource生成View,并加載到DecorView中mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);// 通過DecorView獲取id為ID_ANDROID_CONTENT的ViewViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); return contentParent;
}
總結
執行流程:
- Activity#setContentView()
- PhoneWindow#setContentView()
- PhoneWondow#installDecor()
- PhoneWindow#generateDecor() 創建DecorView
- PhoneWindow#generateLayout() 加載layoutResource并獲取ContentView
- 將自定義布局添加到ContentView中