Android App 生命周期解析:为什么你的 AI 生成的 App 在旋转时仍能存活

发布: (2026年3月2日 GMT+8 08:15)
9 分钟阅读
原文: Dev.to

Source: Dev.to

活动生命周期:五个状态

onCreate() → onStart() → onResume() → [Activity visible and interactive]

                                    onPause() → onStop() → onDestroy()

1. onCreate()

  • 当 Activity 首次创建时调用。
  • 初始化 UI,设置数据绑定。
  • 恢复已保存的状态(后面会详细说明)。

2. onStart()

  • Activity 对用户可见。
  • 启动摄像头、位置服务等资源。
  • 此时尚未可交互。

3. onResume()

  • Activity 现在已完全可交互。
  • 用户可以点击按钮、输入文字等。
  • 启动动画或恢复视频播放。

4. onPause()

  • 用户正在离开该 Activity(另一个应用进入前台)。
  • 在此保存关键数据。
  • 停止动画,暂停视频。
  • 注意: 你只有约 500 ms 的时间,系统可能会在此后杀死你的应用。

5. onStop()

  • Activity 不再可见。
  • 清理占用较大的资源(例如数据库连接)。
  • 系统可能会在此处杀死你的应用以释放内存。

6. onDestroy()

  • Activity 正在被销毁(用户按了返回键或系统正在杀死它)。
  • 最终清理。

问题:配置更改(旋转)

当用户旋转手机时,Android 会销毁当前的 Activity 并从头重新创建它

User rotates phone

onPause() → onStop() → onDestroy()   [old Activity destroyed]

onCreate() → onStart() → onResume()  [new Activity created]

后果

  • 所有局部变量都会丢失。
  • 任何内存中的数据都会消失。
  • UI 状态被重置。
  • 用户会看到 UI 重建时的闪烁/闪光。

这就是许多 AI 生成的应用在旋转时崩溃的原因——开发者没有正确保存状态。

方案 1:使用 ViewModel 在配置更改时保持存活

ViewModel 是一个 Jetpack 组件,能够在配置更改时保持存活。存放在 ViewModel 中的数据 不会 在 Activity 旋转时被销毁。

Kotlin 代码示例

// 1. Define your ViewModel
class UserViewModel : ViewModel() {
    private val _userName = MutableLiveData("")
    val userName: LiveData<String> = _userName

    fun setUserName(name: String) {
        _userName.value = name
    }
}

// 2. In your Activity, use the ViewModel
class MainActivity : AppCompatActivity() {
    private val viewModel: UserViewModel by viewModels()

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

        val nameInput = findViewById<EditText>(R.id.nameInput)

        // When user types, save to ViewModel
        nameInput.addTextChangedListener { text ->
            viewModel.setUserName(text.toString())
        }

        // Observe ViewModel data
        viewModel.userName.observe(this) { name ->
            nameInput.setText(name)
        }
    }
}

为什么这样可行

  • ViewModel 的作用域是 Activity。
  • Android 在配置更改期间会保持它的实例。
  • 数据在旋转时仍然持久化。
  • UI 通过 LiveData 自动更新。

方案 2:使用 Jetpack Compose 与 rememberSaveable

如果您使用 Compose(现代 Android UI 框架),该模式甚至更简单。

@Composable
fun UserScreen() {
    // This state survives rotation because of rememberSaveable
    var userName by rememberSaveable { mutableStateOf("") }

    Column {
        TextField(
            value = userName,
            onValueChange = { userName = it },
            label = { Text("Enter your name") }
        )
        Text("Hello, $userName!")
    }
}

关键差异

Compose 函数旋转时是否保留
remember { } – 状态在销毁时丢失
rememberSaveable { } – 保存到 Bundle 并恢复

Compose 会在 Activity 重新创建时自动恢复已保存的状态。

Compose 重组工作原理

当发生旋转时:

  1. Activity 被销毁rememberSaveable 将其状态保存到 Bundle
  2. Activity 被重新创建rememberSaveableBundle 中恢复状态。
  3. Compose 重新组合 UI 树,使用恢复后的值渲染 TextField
User rotates phone

rememberSaveable saves state → Activity destroyed

Activity recreated → rememberSaveable restores state

Compose recomposes → TextField shows saved text

解决方案 3:保存到 savedInstanceStateonSaveInstanceState

对于更复杂的数据,请使用 onSaveInstanceState() 回调。

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

        val nameInput = findViewById<EditText>(R.id.nameInput)

        // Restore from saved state
        if (savedInstanceState != null) {
            val savedName = savedInstanceState.getString("userName", "")
            nameInput.setText(savedName)
        }
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        val nameInput = findViewById<EditText>(R.id.nameInput)
        outState.putString("userName", nameInput.text.toString())
    }
}

onSaveInstanceState 在 Activity 被销毁之前调用,允许您将原始类型、ParcelableSerializable 放入 Bundle 中。当 Activity 重新创建时,已保存的值可在 onCreate(或 onRestoreInstanceState)中获取。

TL;DR

  • Activity 生命周期 决定了何时可以安全地分配和释放资源。
  • 旋转 会触发完整的销毁/重建周期,清除内存中的状态。
  • ViewModelrememberSaveableonSaveInstanceState 是在配置更改时保留数据的三种主要方式。

实现其中一种(或组合)策略,你的 AI 生成的 Android 应用就能优雅地应对旋转。

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putString("userName", nameInput.text.toString())
}

限制

  • 仅适用于 Parcelable/Serializable 对象。
  • Bundle 大约有 1 MB 的大小限制。
  • 不适合大型数据集。

防止旋转:禁用配置更改 (不推荐)

<!-- Add to your Activity declaration in AndroidManifest.xml -->
<activity
    android:name=".MainActivity"
    android:configChanges="orientation|screenSize|keyboardHidden"
    android:screenOrientation="portrait" />

为什么 要这么做

  • 用户不喜欢不能旋转的应用。
  • 你会破坏依赖旋转的用户的可访问性。
  • 忽视旋转的 AI 生成应用会收到差评。

Source:

当你的应用被杀死:进程死亡

Android 可以在后台杀死整个进程以释放内存。这 不同于 配置更改。

流程

用户将你的应用切到后台

系统需要内存

系统杀死你的进程(调用 onDestroy())

用户返回你的应用

系统重新创建整个应用栈

onSaveInstanceState() 在这里仍然可用,但只能保存 UI 状态。
对于重要数据,请使用持久化存储:

  • Room(本地数据库)
  • SharedPreferences
  • DataStore(Jetpack)

Room 示例

@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

@Dao
interface UserDao {
    @Insert
    suspend fun insertUser(user: User)

    @Query("SELECT * FROM users LIMIT 1")
    fun getUser(): Flow<User>
}

重启后恢复数据

class MainActivity : AppCompatActivity() {
    private val db = AppDatabase.getInstance(this)

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

        lifecycleScope.launch {
            db.userDao().getUser().collect { user ->
                // Restore UI with user data
            }
        }
    }
}

摘要表

场景解决方案是否在旋转后仍存活数据限制
配置更改(旋转)ViewModel + LiveData无限制
配置更改(Compose)rememberSaveable约 1 MB(Bundle
短暂暂停(onPauseViewModel无限制
进程死亡Room / SharedPreferences / DataStore设备存储
用户按返回键未保存不适用

AI 生成的应用程序与生命周期

当您使用 Claude Code 或其他任何 AI 生成 Android 应用时,务必验证

  • ✅ 它是否在旋转时不会崩溃?
  • ✅ 它是否使用 ViewModelrememberSaveable
  • ✅ 它是否将重要数据持久化到数据库中?
  • ✅ 它是否正确实现了用于清理的 onPause()

生成质量较差的应用常见问题

  • 完全忽视生命周期。
  • 旋转时数据丢失。
  • 进程死亡时崩溃。
  • 未保存用户输入。

我们的模板已正确处理所有这些问题。

图示(供参考)

┌─────────────────────────────────────────────────────┐
│               活动生命周期流程               │
└─────────────────────────────────────────────────────┘

                onCreate()

                onStart()

                onResume()   ← [用户交互中]
                ↙       ↖
        onPause()      [旋转:销毁并重新创建]

            onStop()

            onDestroy()

ViewModel 在旋转后仍然存在 ✓
rememberSaveable 在旋转后仍然存在 ✓
局部变量在旋转后不保留 ✗

结论

  • 使用 ViewModelrememberSaveable 来管理 UI 状态。
  • 使用 RoomSharedPreferencesDataStore 来存储持久化数据。
  • onSaveInstanceState() 中保存状态,以应对特殊情况。
  • 在发布前测试旋转。

所有 8 个模板都正确处理了生命周期。

https://myougatheax.gumroad.com

0 浏览
Back to Blog

相关文章

阅读更多 »

移动开发中最危险的消息

如果你开发移动应用,可能至少见过一次这样的提示:“嘿……构建没有安装”。就这样,你的一天被毁了。你…