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中
相关推荐
Zeaon20 分钟前
别再手写筛选栏了:一个可组合的 Flutter 选择组件(5 入口 × 7 委托)
android·flutter
Michaelwubo30 分钟前
mysql8 主从 HA切换
android·adb
墨狂之逸才1 小时前
Android 工业手持机蓝牙扫描失败:为什么同时需要蓝牙和定位权限
android
Android打工仔1 小时前
Kotlin 协程源码解析(七)`delay()` 到底是如何在 `Dispatchers.Main` 上恢复的?
android·kotlin
律宏阔2 小时前
Android 红外功能实现与红外协议开发笔记:ConsumerIrManager、NEC、PWM、曼彻斯特编码
android
mmsx2 小时前
MapLibre 统一图层模型:sealed class + 声明式图层 + XML 持久化
android·源码·地图·maplibre
YUJIANYUE3 小时前
查立得万用查分安卓版(web环境+查询系统免安装单文件一键运行包)
android·前端
天空之城--3 小时前
Android Launcher 性能优化完全指南:从启动到滑动,构建极致流畅的桌面体验
android·性能优化
hunterandroid4 小时前
Android ANR 排查实战:从线上告警到主线程卡点定位
android·前端
TimeFine4 小时前
智能眼镜开发:图片翻译与EXIF的重要性
android