Android应用的调试

Android应用的调试:保留第四版正文机制,以所有者—状态—结果合同、事件轨迹和章专属故障完成可重放验收。

学习目标

  • 能沿“Android应用的调试”的用户事件解释Android组件、状态所有者、线程与销毁边界。
  • 能围绕“掌握 Android Studio 调试工具——Logcat 日志过滤、断点调试、变量监视和堆栈追踪分析。”改出一个可运行结果,并用前后状态而非组件数量验收。
  • 能在旋转、进程重建、拒权、离线或无效输入中选择适用反例,定位首个状态分叉。
  • 能用构建指纹、用户操作、状态快照、原始日志和行为断言独立重放结论,并标明第四版机制与现代targetSdk政策的边界。

Bug 来了——先看黑匣子

用户说「闪退」,你的第一步不是改代码,而是打开 。配合断点和堆栈追踪,大多数问题能在十分钟内定位到文件和行号。

Logcat 过滤

典型崩溃行:

E/AndroidRuntime: FATAL EXCEPTION: main
    java.lang.NullPointerException
    at com.example.MainActivity.onCreate(MainActivity.kt:42)

读法:异常类型 → 你的包名 → 行号

一行 Logcat 日志,拆开看是这五段认清每段的位置,才知道过滤框里该按哪一段筛2024-01-15 10:23:45.123时间戳哪天哪一刻打的12345-12360PID-TID哪个进程 / 线程D级别Verbose…ErrorMainActivityTAG谁打的(过滤主抓手)onCreate called消息正文具体说了什么日志级别(由弱到强)VVerbose最啰嗦:流水账DDebug调试:开发期打点IInfo信息:正常事件WWarn警告:可能有问题EError错误:崩溃在这过滤就靠上面这几段按 level:只看 Error按 tag:只看本 TAG按 regex:组合关键字
一行 Logcat 日志由时间戳、PID-TID、级别、TAG、消息正文拼成。看懂分段后,过滤就是 在「级别 / TAG / 正则」三个维度上筛——把无关噪音挡在外面,崩溃行(Error)一眼可见。
分步1 / 4

① 选择日志级别

在 Logcat 顶部下拉框将 Log Level 设为 Error(或 Warn+Error),过滤掉无关的 Debug 和 Verbose 输出。崩溃日志的优先级一定是 Error。

调试闭环:复现 → 定位 → 修复 → 验证未解决 → 回到复现重来通过 ✓复现稳定重现这个 bug定位看 Logcat / 读堆栈 / 下断点假设修复改最可疑的那一行验证再跑一遍复现路径普通条件异常断点三种:堆栈追踪从顶向下读第一行 ≈ 崩溃点卡死无响应?查 ANRANR = 主线程阻塞 > 5s
调试不是一次性动作,而是一个闭环:先稳定复现,再用 Logcat / 堆栈 / 断点定位, 提出修复假设后回到复现路径验证——没解决就再转一圈,直到验证通过。

断点调试

类型用途
普通断点暂停查看变量
条件断点index == 99,循环里只停一次
异常断点Run → View Breakpoints → Any exception,崩溃即停

堆栈追踪

从下往上读,第一个你的包名通常是根因:

at com.example.MainActivity.loadData(MainActivity.kt:42)  ← 根因
at com.example.MainActivity.onCreate(MainActivity.kt:18)
at android.app.Activity.performCreate(...)

小结

  • Crash → Logcat Error + 堆栈第一行自己的代码
  • ANR → 主线程堆栈找阻塞点
  • 断点:条件断点省时间,异常断点抓崩溃

练习

问题 1:“第5章 Debugging Android Apps”覆盖哪些正式节点和项目主线?

问题 2:怎样建立本页最小可执行实验?

问题 3:为什么只在正常点击路径运行不能证明完成?

问题 4:怎样设计能推翻当前实现的反例?

问题 5:从第4版语境迁移到现代目标SDK时如何控制变量?

问题 6:本页达到独立交接标准需要什么?

名词解释

本章出现的专业名词,用大白话再讲一遍。

Logcat

Android Studio 中显示系统和应用运行时日志的窗口,按时间与级别输出调试信息。排查闪退、异常的第一站。

ANR

Application Not Responding——主线程阻塞超约 5 秒,系统弹窗。常见原因:主线程 IO、死锁、过度布局。

堆栈追踪(Stack Trace)

异常时的方法调用链。从下往上读,定位第一个业务代码帧。

“Android应用的调试”不使用未获授权的纸书正文;InformIT出版信息授权电子版完整目录只用于确认第四版32章、269个正式目录节点和时代语境,第四版官方勘误用于识别工具链变更。下列中文解释、图示、交互、代码与练习均为独立教学重写,平台行为再以Android Developers的一手文档复核。

为什么“Android应用的调试”必须回到可观察状态

“Android应用的调试”的学习结果不是记住类名,而是能预测“掌握 Android Studio 调试工具——Logcat 日志过滤、断点调试、变量监视和堆栈追踪分析。”在一次输入、一次重建和一次失败中的不同状态,并指出哪条Android合同产生差异。

第四版机制逐项深读

5. Debugging Android Apps

在“Android应用的调试”中,“5. Debugging Android Apps”从症状回溯首个异常帧、日志事件或状态分叉;修复证据必须包含可复现输入和失败前后的同一断言。

Exceptions and Stack Traces

在“Android应用的调试”中,分析“Exceptions and Stack Traces”区分编译、运行时、布局、线程与资源问题,避免在后续连锁报错处停止定位。

Android-Specific Debugging

在“Android应用的调试”中,“Android-Specific Debugging”从症状回溯首个异常帧、日志事件或状态分叉;修复证据必须包含可复现输入和失败前后的同一断言。

Challenge: Exploring the Layout Inspector

在“Android应用的调试”中,“Challenge: Exploring the Layout Inspector”的视觉正确性必须与语义树一致;看得见但读屏无名称、焦点不可达或点击区过小仍判失败。

Challenge: Exploring the Profiler

在“Android应用的调试”中,分析“Challenge: Exploring the Profiler”区分编译、运行时、布局、线程与资源问题,避免在后续连锁报错处停止定位。

“Android应用的调试”验收回顾

“Android应用的调试”只有在构建指纹、用户操作、状态快照、原始日志和行为断言能够从相同基线再次得到相同断言时才通过;第四版机制与现代平台政策分别记录,不用新API名称掩盖旧行为。

← 上一页:UI状态的保存与恢复 · 下一页:第二个Activity →

章专属可重放状态实验

先预测“重放最小失败用例并一次只改变一个原因”发生后,测试、Logcat、断点与问题工件的责任人应怎样改变失败输入、线程、异常、调用栈和修复假设;再操作三个实验。第四版示例与当前 Android 政策分别记录,实验不把新 API 名称倒填为原书内容。

实验一:所有者—状态—结果合同

选择任一正式目录节点和正常/边界场景,检查它是否真的进入本章状态合同。目录标题只有同时出现在解释、可视状态和交付证据中才算覆盖。

Owner · state · observable result

Android应用的调试:状态合同

从稳定失败、堆栈首个业务帧和设备状态定位 Android 缺陷

验证场景

第四版正式目录节点

debugging · 正常任务

5. Debugging Android Apps固定 SDK、设备配置和初始状态,触发“重放最小失败用例并一次只改变一个原因”

状态所有者测试、Logcat、断点与问题工件的责任人
受控状态失败输入、线程、异常、调用栈和修复假设
触发事件重放最小失败用例并一次只改变一个原因

冻结入口:5. Debugging Android Apps

记录测试、Logcat、断点与问题工件的责任人的初始失败输入、线程、异常、调用栈和修复假设

观察:失败测试、完整堆栈、断点快照、修复差异和回归结果中的“5. Debugging Android Apps”轨迹

预期:由测试、Logcat、断点与问题工件的责任人提交失败输入、线程、异常、调用栈和修复假设,并持续满足“同一失败输入在修复前稳定失败、修复后稳定通过且邻近用例不回归”

实验二:事件与生命周期轨迹

沿五次转换逐步执行“重放最小失败用例并一次只改变一个原因”。每一步只允许测试、Logcat、断点与问题工件的责任人按职责提交状态,并持续核对“同一失败输入在修复前稳定失败、修复后稳定通过且邻近用例不回归”。

Deterministic event replay

Android应用的调试:事件轨迹

选择一次状态转换1 / 5

不变量:同一失败输入在修复前稳定失败、修复后稳定通过且邻近用例不回归

交付证据:失败测试、完整堆栈、断点快照、修复差异和回归结果

实验三:章专属反例与同输入恢复

注入“捕获异常或删除日志让界面不崩,却没有修复无效状态”,保存第一个偏离点;撤销后以完全相同的 SDK、设备状态和用户事件重放。只有失败测试、完整堆栈、断点快照、修复差异和回归结果一起恢复才算修复。

Fault · cancel · restore

Android应用的调试:反例与恢复

故障:捕获异常或删除日志让界面不崩,却没有修复无效状态

1. 冻结输入一致

第 1 次使用相同 SDK、设备配置、初始状态与用户事件

2. 注入边界一致

保持正常输入不变,仅注入“捕获异常或删除日志让界面不崩,却没有修复无效状态”

3. 检查所有者一致

同一失败输入在修复前稳定失败、修复后稳定通过且邻近用例不回归

4. 核对结果一致

失败测试、完整堆栈、断点快照、修复差异和回归结果

讨论

评论区加载中…