onCreate — 什么是 Android 中的 Activity 初始化

作者: IT Sectr 发布日期: 2026-03-03 阅读时间: 10 分钟

onCreate — 是 Android 中 Activity 和 Fragment 生命周期的第一个也是唯一必需的方法。系统在创建组件时调用它一次,传入带有先前保存状态的 Bundle 参数。在 onCreate 内部,开发者初始化用户界面,绑定 View 元素,配置事件处理器,并从 savedInstanceState 恢复数据。没有正确的 onCreate 实现,任何 Android 应用都无法启动 — 它是每个屏幕的入口点。有关 Activity 通用生命周期的更多信息,请阅读文章 Activity Lifecycle

要点

  • onCreate — 生命周期的第一个也是唯一必需的方法;在创建 Activity 或 Fragment 时调用一次
  • Bundle 参数 — savedInstanceState 包含在 onSaveInstanceState 中保存的数据,如果 Activity 是首次创建则为 null
  • setContentView — Activity 的 onCreate 内部必需调用;将 XML 布局与代码关联
  • UI 初始化 — findViewById、配置 RecyclerView 适配器、设置点击监听器 — onCreate 的典型任务
  • Fragment.onCreate — 与 Activity 不同:这里不调用 setContentView,布局通过 onCreateView 传递
  • 时间限制 — onCreate 必须在 5 秒内完成(ANR 阈值),长时间操作移至后台线程
  • ViewModel 和 onCreate — 在 onCreate 中初始化 ViewModel 允许数据在屏幕旋转时无损失地存活

Android 中的 onCreate 是什么

onCreate — 是 Android 在创建新的 Activity 或 Fragment 实例时调用的回调方法。这是用户屏幕代码的第一个入口点:在调用 onCreate 之前,不执行任何用户代码。系统向该方法传入 Bundle 参数,其中包含先前保存的数据(重新创建时)或为 null(首次启动时)。

onCreate 方法定义在 android.app.Activity 类和 androidx.fragment.app.Fragment 类中。两种变体执行类似的任务:组件初始化、UI 配置和状态恢复。然而,具体实现有所不同 — Activity 使用 setContentView 加载布局,而 Fragment 通过 onCreateView 返回 View。开发者必须在 Activity 中至少重写 onCreate — 否则 Android 无法显示屏幕。

onCreate 在 Activity 实例的整个生命周期中严格调用一次。即使在屏幕旋转时,新的 Activity 实例也会收到带有前一个实例 Bundle 的新 onCreate 调用。这一特性使 onCreate 成为一次性初始化的理想场所:加载数据、创建适配器、通过 Dagger 或 Hilt 配置 DI 组件。

Activity 中的 onCreate

在 Activity 中,onCreate 方法执行四个关键任务:加载 layout 布局、初始化 View 元素、从 Bundle 恢复状态和配置主要事件处理器。onCreate 中的强制最小代码 — 调用 super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)

kotlin
class MainActivity : AppCompatActivity() {
    private var binding: ActivityMainBinding? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // ViewBinding — findViewById 的现代替代品
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding?.root)

        // 使用 binding 进行初始化
        binding?.apply {
            welcomeText.text = getString(R.string.welcome)
            startButton.setOnClickListener { startGame() }
        }

        // 状态恢复
        if (savedInstanceState != null) {
            score = savedInstanceState.getInt("score", 0)
            binding?.scoreText?.text = score.toString()
        }
    }
}

现代实践 — 使用 ViewBinding 替代 findViewById。ViewBinding 在编译阶段生成 ActivityMainBinding 类,消除了错误 ID 导致的问题并减少了样板代码量。Google 从 Android Studio 3.6 开始推荐 ViewBinding 作为 Activity 和 Fragment 中访问 View 的标准方式。

onCreate 中的操作顺序必须严格:先 super,然后 setContentView,之后才是其他所有操作。在 setContentView 之前调用 findViewById 会返回 null — 布局尚未加载,View 元素在层次结构中不存在。这是 Android 初学者最常见的错误之一。

Fragment 中的 onCreate

Fragment 中的 onCreate 与 Activity 不同:这里不调用 setContentView,仅执行与 UI 无关的数据初始化。Fragment 将组件的创建和 View 的创建分为两个独立的方法:onCreate(调用一次)和 onCreateView(在 View 创建或重新创建时每次调用)。

kotlin
class UserListFragment : Fragment() {
    private lateinit var viewModel: UserViewModel
    private var binding: FragmentUserListBinding? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // ViewModel 初始化 — 将承受 View 的重新创建
        viewModel = ViewModelProvider(this)[UserViewModel::class.java]

        // 来自 FragmentManager 的参数
        arguments?.let {
            viewModel.loadUser(it.getString("user_id") ?: "")
        }

        // 旋转时保存
        retainInstance = true
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentUserListBinding.inflate(inflater, container, false)
        return binding!!.root
    }
}

Activity 和 Fragment 的 onCreate 之间的关键区别:Fragment 中的 onCreate 不应包含与 View 相关的代码,因为 View 可能被销毁并重新创建(例如,在切换 ViewPager 标签时),而 onCreate 仅调用一次。加载数据、配置 ViewModel 和初始化适配器 — onCreate 的任务,而绑定 View — onViewCreated 的任务。

savedInstanceState 和状态恢复

onCreate 中的 savedInstanceState 参数 — 是保存和恢复 Activity 或 Fragment 临时状态的机制。当系统销毁 Activity 时(屏幕旋转、内存不足),调用 onSaveInstanceState(),开发者将键值对放入 Bundle 中。在创建新实例时,此 Bundle 在 onCreate 中返回。

Bundle 支持以下数据类型:String、Integer、Boolean、Long、Float、Double、它们的数组,以及 Parcelable 和 Serializable 对象。对于复杂对象,使用 Parcelable — 这是一种更高效的序列化机制,特定于 Android。Bundle 的大小限制约为 500 KB — 超出限制会导致 TransactionTooLargeException 异常。

kotlin
companion object {
    private const val KEY_USER_NAME = "user_name"
    private const val KEY_SCORE = "score"
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_game)

    if (savedInstanceState != null) {
        userName = savedInstanceState.getString(KEY_USER_NAME) ?: ""
        currentScore = savedInstanceState.getInt(KEY_SCORE)
    }
}

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putString(KEY_USER_NAME, userName)
    outState.putInt(KEY_SCORE, currentScore)
}

理解这一点很重要:当用户通过 finish() 或按「返回」按钮显式关闭 Activity 时,不会调用 onSaveInstanceState。系统认为在这种情况下用户有意识地结束工作,因此不需要保存状态。因此,不应仅依赖 savedInstanceState 进行长期数据存储 — 请使用 Room、DataStore 或 SharedPreferences。

onCreate 的时间安排和限制

onCreate 在主(UI)线程中执行,系统在其完成之前等待,然后才在屏幕上显示 Activity。如果 onCreate 持续超过 5 秒,系统会显示 ANR(Application Not Responding)对话框并建议用户关闭应用。长时间操作,如从网络加载数据或从数据库读取,应移至后台线程。

根据 Google Android Performance(2025)的建议,onCreate 应在中端设备上在少于 1 秒内完成。为此,您应:使用延迟初始化(Kotlin 中的 lazy 委托),将繁重数据的加载推迟到 onResume 或通过协程,对很少使用的 UI 组件应用 ViewStub,通过 Android Vitals 分析启动时间。

kotlin
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // 延迟初始化 — 对象仅在首次访问时创建
    val heavyData by lazy {
        HeavyDataLoader.load()
    }

    // 通过 lifecycleScope 在后台线程中加载数据
    lifecycleScope.launch(Dispatchers.IO) {
        val users = userDao.getAllUsers()
        withContext(Dispatchers.Main) {
            adapter.submitList(users)
        }
    }
}

性能分析工具:Android Studio Profiler(CPU 选项卡)显示每个方法的精确执行时间。在 Android Vitals(Google Play 控制台)中,您可以监控「冷启动时间」指标 — 如果您的 Activity 的 onCreate 超过 500 毫秒,控制台会将其标记为性能问题。我们在 IT Sectr 使用 Macrobenchmark 测试来自动控制 CI 流水线中每个 Activity 的启动时间。

ViewModel 和 onCreate

ViewModel — 在 onCreate 中初始化必须承受屏幕旋转的数据的最佳方式。ViewModel 通过 ViewModelProvider 在 onCreate 中创建,并在配置更改时自动保存。当 Activity 在旋转后重新创建时,ViewModel 保留在内存中,onCreate 接收相同的 ViewModel 而不会丢失数据。

kotlin
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_profile)

    // ViewModel 创建一次并承受配置更改
    val viewModel: ProfileViewModel =
        ViewModelProvider(this)[ProfileViewModel::class.java]

    // LiveData 观察 — UI 在数据更改时自动更新
    viewModel.user.observe(this) { user ->
        binding?.userName?.text = user.name
        binding?.userEmail?.text = user.email
    }

    // 如果 ViewModel 刚创建则加载数据
    if (savedInstanceState == null) {
        viewModel.loadProfile(userId)
    }
}

ViewModel + LiveData/StateFlow 组合无需手动保存到 Bundle 即可解决屏幕旋转问题。ViewModel 将数据存储在内存中,LiveData 在重新创建时自动重新订阅 Activity,StateFlow(来自 Kotlin Coroutines)通过协程支持增加了响应式能力。这是 Google 在 Guide to App Architecture 指南中推荐的标准架构。

使用 onCreate 时的常见错误

即使是有经验的开发人员也会在 onCreate 中犯典型错误。让我们来看五个最常见的问题及其避免方法。

在 setContentView 之前使用 View

最常见的错误 — 在调用 setContentView 之前尝试通过 findViewById 查找 View。所有 View 元素在布局膨胀时创建,因此在 setContentView 之前对 findViewById 的任何引用都会返回 null,并在尝试使用 View 时导致 NullPointerException。解决方案:严格顺序 — 先 super,然后 setContentView,之后 findViewById 或 ViewBinding。

长时间操作阻塞 UI 线程

直接在 onCreate 中从网络加载数据、从数据库读取或处理大型数组会阻塞第一帧的渲染。用户在 onCreate 完成之前看到黑屏,这降低了对应用速度的感知。解决方案:对异步操作使用 lifecycleScope.launch,在加载完成之前显示骨架(占位 UI)。

忽略 savedInstanceState

如果在屏幕旋转时不从 Bundle 恢复状态,用户将丢失所有未保存的输入:表单字段中的文本、滚动位置、选中的元素。解决方案:始终在 onCreate 中检查 savedInstanceState != null 以恢复数据,即使状态丢失看似不太可能。

通过匿名类导致内存泄漏

onCreate 中的匿名类和 lambda 可能在 Activity 被销毁后隐式持有对它的引用。例如,在 onCreate 中创建的 Handler 即使在 Activity 被销毁后仍继续执行延迟任务。解决方案:使用 LifecycleObserver、ViewModel 和 lifecycleScope,它们在销毁时自动取消任务。

Fragment 的 onCreate 中过度初始化

在 Fragment 的 onCreate 中初始化 View — 逻辑错误,因为 View 可以在不调用 onCreate 的情况下重新创建。如果在 onCreate 中设置了监听器而 View 在 onCreateView 中绑定,在重新创建时监听器将保留在旧的 View 上。解决方案:所有与 View 相关的工作在 onViewCreated 中执行,onCreate 仅保留用于数据层的初始化。

常见问题

在 Activity 中重写 onCreate 是必需的吗?

是的,重写 onCreate 是必需的对于任何显示用户界面的 Activity。否则无法调用 setContentView 和加载 XML 布局。如果 Activity 没有 UI(例如,透明 Activity 存根),onCreate 仍然被重写,但不调用 setContentView。

onCreate 能否在不销毁 Activity 的情况下再次被调用?

不,onCreate 不能为同一个 Activity 实例再次调用。如果 Activity 被销毁并重新创建(屏幕旋转、内存不足),这已经是一个新的实例并带有新的 onCreate 调用。例外是 recreate() 方法,它强制销毁并重新创建 Activity,但这也是新实例的重新创建。

如果不调用 super.onCreate 会发生什么?

如果不调用 super.onCreate(savedInstanceState),Android Runtime 将抛出 SuperNotCalledException 异常,应用将崩溃。系统严格要求每个重写的生命周期方法调用其 super 版本 — 这保证了内部状态机的正确运行。

Activity 中的 onCreate 与 Fragment 中的 onCreate 有何不同?

主要区别:Activity 中的 onCreate 通过 setContentView 加载 UI,而 Fragment 中的 onCreate 仅初始化数据。Fragment 在单独的 onCreateView 方法中创建 View,该方法可能被多次调用(例如,切换标签时),而 Fragment 的 onCreate 在 Fragment 实例的生命周期内只调用一次。

如何将数据从 onCreate 传递到其他方法?

在 onCreate 中初始化的数据存储在 Activity 或 Fragment 类的字段中。例如,private lateinit var binding: ActivityMainBinding 在类级别声明,在 onCreate 中初始化,并在所有后续方法中可用。对于承受屏幕旋转的数据,使用带有 LiveData 或 StateFlow 的 ViewModel。

总结

  • onCreate — 必需的生命周期方法,在创建 Activity 或 Fragment 时调用一次
  • setContentView — Activity 的必需调用,加载 XML 布局;对于 Fragment,布局通过 onCreateView 加载
  • savedInstanceState — 重新创建时带有已保存状态的 Bundle;首次启动时为 null
  • 时间限制 — onCreate 应在 1 秒内完成,长时间操作移至协程
  • ViewModel — 在 onCreate 中初始化 ViewModel 解决了屏幕旋转时数据丢失的问题
  • Fragment vs Activity — Fragment 的 onCreate 不包含 UI 代码,Activity 的 onCreate 通过 setContentView 加载布局
  • 五种典型错误 — 在 setContentView 之前使用 View、阻塞 UI、忽略 Bundle、内存泄漏、Fragment.onCreate 中的 UI 代码

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读