Android setContentView()源码分析

文章目录

  • [Android setContentView()源码分析](#Android setContentView()源码分析)
    • 前提
    • [setContentView() 源码分析](#setContentView() 源码分析)
    • 总结

Android setContentView()源码分析

前提

Activity 的生命周期与 ActivityThread 相关,调用 startActivity() 时,会调用 ActivityThread#performLaunchActivity(),接着调用 Activity#attach() 并在其中创建 PhoneWindow。

Activity 持有 PhoneWindow 对象,PhoneWindow 持有 DecorView。

java 复制代码
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;
}
java 复制代码
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) {

        // 创建PhoneWindow
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
    }
}
java 复制代码
public class PhoneWindow extends Window {
    private DecorView mDecor;
    ViewGroup mContentParent;
}

setContentView() 源码分析

java 复制代码
// Activity#setContentView()
public void setContentView()(@LayoutRes int layoutResID) {
    // 调用PhoneWindow#setContentView()
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
}

public Window getWindow() {
    return mWindow;
}
java 复制代码
// PhoneWindow#setContentView()
// 核心代码:
public void setContentView()(int layoutResID) {
    if (mContentParent == null) {
        // 初始化DecorView
        installDecor();
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
    }
    // 将布局添加到ContentView中
    mLayoutInflater.inflate(layoutResID, mContentParent);
}
java 复制代码
// PhoneWindow#installDecor()
private void installDecor() {
    mForceDecorInstall = false;
    if (mDecor == null) {
        // 创建DecorView
        mDecor = generateDecor(-1);
    } else {
        mDecor.setWindow(this);
    }
    if (mContentParent == null) {
        // 获取ContentView
        mContentParent = generateLayout(mDecor);
    }
}
java 复制代码
// 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继承自FrameLayout
    return new DecorView(context, featureId, this, getAttributes());
}
java 复制代码
// PhoneWindow#generateLayout()
// 核心代码:
protected ViewGroup generateLayout(DecorView decor) {
    // 布局id
    int layoutResource;
    int features = getLocalFeatures();
   	// 省略layoutResource赋值流程,根据主题赋值
	// ...
    // 加载layoutResource生成View,并加载到DecorView中
    mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
	// 通过DecorView获取id为ID_ANDROID_CONTENT的View
    ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);    

    return contentParent;
}

总结

执行流程:

  • Activity#setContentView()
  • PhoneWindow#setContentView()
  • PhoneWondow#installDecor()
    • PhoneWindow#generateDecor() 创建DecorView
    • PhoneWindow#generateLayout() 加载layoutResource并获取ContentView
  • 将自定义布局添加到ContentView中
相关推荐
不爱说话郭德纲8 小时前
告别漫长的HbuilderX云打包排队!uni-app x 安卓本地打包保姆级教程(附白屏、包体积过大排坑指南)
android·前端·uni-app
Sinclair12 小时前
简单几步,安卓手机秒变服务器,安装 CMS 程序
android·服务器
雮尘15 小时前
手把手带你玩转Android gRPC:一篇搞定原理、配置与客户端开发
android·前端·grpc
ktl17 小时前
Android 编译加速/优化 80%:一个文件搞定,零侵入零配置
android
alexhilton1 天前
使用FunctionGemma进行设备端函数调用
android·kotlin·android jetpack
冬奇Lab1 天前
InputManagerService:输入事件分发与ANR机制
android·源码阅读
张小潇1 天前
AOSP15 Input专题InputManager源码分析
android·操作系统
RdoZam1 天前
Android-封装基类Activity\Fragment,从0到1记录
android·kotlin
奥陌陌2 天前
android 打印函数调用堆栈
android
用户985120035832 天前
Compose Navigation 3 深度解析(二):基础用法
android·android jetpack