第二个Activity
第二个Activity:保留第四版正文机制,以所有者—状态—结果合同、事件轨迹和章专属故障完成可重放验收。
学习目标
- 能沿“第二个Activity”的用户事件解释Android组件、状态所有者、线程与销毁边界。
- 能围绕“学会启动第二个 Activity——显式 Intent、Activity 间传递数据、Activity Result API 接收返回结果。”改出一个可运行结果,并用前后状态而非组件数量验收。
- 能在旋转、进程重建、拒权、离线或无效输入中选择适用反例,定位首个状态分叉。
- 能用Intent合同、解析目标、权限、返回结果和重复副作用独立重放结论,并标明第四版机制与现代targetSdk政策的边界。
一个 App 里通常不止一个屏幕
列表页点进详情、设置页返回主界面——每个屏幕通常是一个 ↡Android 中承载单一界面的组件,通过 Intent 启动,在返回栈中按后进先出管理。。用 ↡显式指定目标组件类名的 Intent,用于应用内页面跳转。 告诉系统「打开哪个 Activity」。
启动第二个 Activity
// CrimeListActivity.kt
val intent = Intent(this, CrimeDetailActivity::class.java)
startActivity(intent)传递数据
intent.putExtra("crime_id", crime.id)
intent.putExtra("crime_title", crime.title)
// CrimeDetailActivity.kt
val crimeId = intent.getStringExtra("crime_id")复杂对象用 Parcelable(Kotlin @Parcelize)或 Serializable,推荐 Parcelable。
Activity Result API
private val detailLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val updatedId = result.data?.getStringExtra("updated_id")
// 刷新列表
}
}
fun openDetail(crimeId: String) {
val intent = Intent(this, CrimeDetailActivity::class.java)
intent.putExtra("crime_id", crimeId)
detailLauncher.launch(intent)
}
// 详情页返回
setResult(Activity.RESULT_OK, Intent().putExtra("updated_id", crime.id))
finish()① 列表启动详情
列表页调用 detailLauncher.launch(intent) 启动详情 Activity。intent 中携带 crime_id 等必要数据,详情页在 onCreate 中通过 getStringExtra 读取。
val intent = Intent(this, CrimeDetailActivity::class.java)
intent.putExtra("crime_id", crime.id)
detailLauncher.launch(intent)返回栈
为什么 startActivity 启动新 Activity 后按返回键能回到上一个?因为系统把同任务里的 Activity 放进一个↡后进先出的 Activity 栈。按 Back 弹出当前 Activity,显示前一个。(back stack,后进先出):启动新 Activity = 压栈、它成为栈顶并显示在屏幕上;按返回键 = 栈顶出栈销毁,下面那个浮上来重新显示。栈顶永远是用户当前看到的那一屏——这也是上面那条「忘记 finish()」陷阱的根源:没 finish,详情页就一直赖在栈顶。
第 1 / 5 步 · ① App 启动:CrimeListActivity 入栈,成为栈顶(也是栈底),当前可见
点击播放,看一次「点进详情、再按返回」如何在返回栈里压栈又出栈;栈顶始终是当前屏幕上的那个 Activity。可暂停、单步、拖进度逐帧观察。
小结
- 显式 Intent +
startActivity/ Result API - putExtra / getXxxExtra 传简单数据
- setResult + finish 回传;检查 resultCode
练习
问题 1:“第6章 Your Second Activity”覆盖哪些正式节点和项目主线?
问题 2:怎样建立本页最小可执行实验?
问题 3:为什么只在正常点击路径运行不能证明完成?
问题 4:怎样设计能推翻当前实现的反例?
问题 5:从第4版语境迁移到现代目标SDK时如何控制变量?
问题 6:本页达到独立交接标准需要什么?
名词解释
本章出现的专业名词,用大白话再讲一遍。
- Activity
Android 中承载单一界面的组件,通过 Intent 启动,在返回栈中按后进先出管理。
- 显式 Intent
通过 setClass/setComponent 指定目标 Activity 的 Intent,用于应用内导航。
- Activity Result API
registerForActivityResult + ActivityResultContract,类型安全地启动 Activity 并接收结果。
- 返回栈
后进先出的 Activity 栈。按 Back 弹出当前 Activity,显示前一个。
“第二个Activity”不使用未获授权的纸书正文;InformIT出版信息与授权电子版完整目录只用于确认第四版32章、269个正式目录节点和时代语境,第四版官方勘误用于识别工具链变更。下列中文解释、图示、交互、代码与练习均为独立教学重写,平台行为再以Android Developers的一手文档复核。
为什么“第二个Activity”必须回到可观察状态
“第二个Activity”的学习结果不是记住类名,而是能预测“学会启动第二个 Activity——显式 Intent、Activity 间传递数据、Activity Result API 接收返回结果。”在一次输入、一次重建和一次失败中的不同状态,并指出哪条Android合同产生差异。
第四版机制逐项深读
6. Your Second Activity
在“第二个Activity”中,“6. Your Second Activity”通过显式Intent启动目标并以extras/result交换最小数据;发送方、接收方和进程重建都必须验证缺失、类型错误和重复返回。
Setting Up a Second Activity
在“第二个Activity”中,“Setting Up a Second Activity”通过显式Intent启动目标并以extras/result交换最小数据;发送方、接收方和进程重建都必须验证缺失、类型错误和重复返回。
Starting an Activity
在“第二个Activity”中,“Starting an Activity”通过显式Intent启动目标并以extras/result交换最小数据;发送方、接收方和进程重建都必须验证缺失、类型错误和重复返回。
Passing Data Between Activities
在“第二个Activity”中,“Passing Data Between Activities”通过显式Intent启动目标并以extras/result交换最小数据;发送方、接收方和进程重建都必须验证缺失、类型错误和重复返回。
How Android Sees Your Activities
在“第二个Activity”中,“How Android Sees Your Activities”若依赖第四版时期API,应分开说明原书机制与现代平台政策,并用Android官方文档核对迁移边界。
Challenge: Closing Loopholes for Cheaters
在“第二个Activity”中,“Challenge: Closing Loopholes for Cheaters”用于推翻“学会启动第二个 Activity——显式 Intent、Activity 间传递数据、Activity Result API 接收返回结果。”的顺利路径:先写预期,再引入一个边界输入、重建或平台差异,并用状态、日志与用户结果解释首个分叉。
Challenge: Tracking Cheat Status by Question
在“第二个Activity”中,“Challenge: Tracking Cheat Status by Question”用于推翻“学会启动第二个 Activity——显式 Intent、Activity 间传递数据、Activity Result API 接收返回结果。”的顺利路径:先写预期,再引入一个边界输入、重建或平台差异,并用状态、日志与用户结果解释首个分叉。
“第二个Activity”验收回顾
“第二个Activity”只有在Intent合同、解析目标、权限、返回结果和重复副作用能够从相同基线再次得到相同断言时才通过;第四版机制与现代平台政策分别记录,不用新API名称掩盖旧行为。
← 上一页:Android应用的调试 · 下一页:SDK版本与兼容性 →
章专属可重放状态实验
先预测“启动第二界面、旋转、返回与重复结果到达”发生后,发送 Activity、目标 Activity 与 ActivityResult 合同应怎样改变题目答案、作弊决定、返回结果和已处理标记;再操作三个实验。第四版示例与当前 Android 政策分别记录,实验不把新 API 名称倒填为原书内容。
实验一:所有者—状态—结果合同
选择任一正式目录节点和正常/边界场景,检查它是否真的进入本章状态合同。目录标题只有同时出现在解释、可视状态和交付证据中才算覆盖。
Owner · state · observable result
第二个Activity:状态合同
以显式 Intent 启动 CheatActivity,并用最小 extras 与结果合同交换数据
验证场景
第四版正式目录节点
second-activity · 正常任务
6. Your Second Activity:固定 SDK、设备配置和初始状态,触发“启动第二界面、旋转、返回与重复结果到达”
冻结入口:6. Your Second Activity
记录发送 Activity、目标 Activity 与 ActivityResult 合同的初始题目答案、作弊决定、返回结果和已处理标记
观察:Intent extras、实例 ID、结果码、消费标记和题目状态中的“6. Your Second Activity”轨迹
预期:由发送 Activity、目标 Activity 与 ActivityResult 合同提交题目答案、作弊决定、返回结果和已处理标记,并持续满足“缺失或重复结果不能让 GeoQuiz 错记作弊状态”
实验二:事件与生命周期轨迹
沿五次转换逐步执行“启动第二界面、旋转、返回与重复结果到达”。每一步只允许发送 Activity、目标 Activity 与 ActivityResult 合同按职责提交状态,并持续核对“缺失或重复结果不能让 GeoQuiz 错记作弊状态”。
Deterministic event replay
第二个Activity:事件轨迹
不变量:缺失或重复结果不能让 GeoQuiz 错记作弊状态
交付证据:Intent extras、实例 ID、结果码、消费标记和题目状态
实验三:章专属反例与同输入恢复
注入“目标 Activity 重建后再次返回同一结果,发送方重复提交”,保存第一个偏离点;撤销后以完全相同的 SDK、设备状态和用户事件重放。只有Intent extras、实例 ID、结果码、消费标记和题目状态一起恢复才算修复。
Fault · cancel · restore
第二个Activity:反例与恢复
故障:目标 Activity 重建后再次返回同一结果,发送方重复提交
第 1 次使用相同 SDK、设备配置、初始状态与用户事件
保持正常输入不变,仅注入“目标 Activity 重建后再次返回同一结果,发送方重复提交”
缺失或重复结果不能让 GeoQuiz 错记作弊状态
Intent extras、实例 ID、结果码、消费标记和题目状态