Android setContentView()源码分析
文章目录
- 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中