1.4 实验:调试Android程序
1.1 实验目标
本实验完成标准:
- 能在 Android 项目中的 Kotlin 代码里添加、删除、启用和禁用断点
- 能使用 Step Over、Step Into、Step Out 控制程序执行
- 能在 Variables 与 Watches 面板查看变量值变化
1.2 导入实验项目
本实验不再从空白模板新建项目,直接导入现有工程。
📦 下载实验项目压缩包(DebugDemo.zip)请按以下顺序一次完成导入:
- 从资源目录获取
DebugDemo.zip,并解压到合适目录(路径避免中文和空格) - 在 Android Studio 中点击 Open(或 File → Open…)
- 选择解压后的
DebugDemo项目根目录(包含settings.gradle.kts的那一层) - 首次弹窗时点击 Trust Project
- 等待 Gradle Sync 完成(出现
BUILD SUCCESSFUL) - 点击一次 Run ‘app’,确认项目可正常启动
详细图文可参考《1.3 导入已有 Android 项目》。
2.1 实现 printLogs() 函数
在 MainActivity.kt 的 printLogs() 函数体中填入日志代码,将姓名与学号替换为你自己的信息:
import ...import android.util.Log
class MainActivity : AppCompatActivity() {
...
private fun printLogs() { val name = "张三" val id = "20260001" Log.v("DebugDemo", "$name-$id 详细:onClick 触发") Log.d("DebugDemo", "$name-$id 调试:执行前") Log.i("DebugDemo", "$name-$id 信息:计算结果=${10 / 2}") Log.w("DebugDemo", "$name-$id 警告:这是一条警告示例") try { val risky = 10 / 0 Log.d("DebugDemo", "$name-$id 调试:risky=$risky") } catch (e: Exception) { Log.e("DebugDemo", "$name-$id 错误:发生了异常", e) } }}✅ 预期效果:printLogs() 函数中包含 Log.v、Log.d、Log.i、Log.w、Log.e 五个级别日志,日志内容带有姓名和学号。
2.2 查看 Logcat 输出
- 打开底部 Logcat 窗口(也可通过菜单 View → Tool Windows → Logcat 打开)
- 在 Logcat 顶部左侧的设备选择器中,选择当前运行的模拟器
- 在日志过滤规则输入框中输入
package:mine tag:DebugDemo,只显示我们刚才添加的日志
package:mine过滤出当前应用的日志(mine是 Android Studio 内置的别名,代表当前运行的应用包)
tag:DebugDemo过滤出我们使用DebugDemo作为 Tag
- 点击工具栏 Run ‘app’ 运行程序,等待应用完全启动
- 在设备(或模拟器)上点击 第一步:打印日志(Logcat 实验) 按钮,触发日志输出
✅ 预期效果:Logcat 中可看到五种级别日志(详细/调试/信息/警告/错误)和异常堆栈信息。
4.1 添加断点
在以下三行左侧行号栏单击,出现红色圆点:
DebugLab.runDemo()中val finalTotal = calculateTotal(...)DebugLab.calculateTotal()中val discounted = applyDiscount(...)DebugLab.applyDiscount()中return (price * discountRate).toInt()
4.2 启动调试
Android Studio 提供两种方式进入断点调试:
方式一:Debug ‘app’(首次调试推荐)
- 点击 Android Studio 顶部工具栏 Debug ‘app’(小甲虫图标)
- Android Studio 会以调试模式重新安装/启动应用
方式二:Attach Debugger(程序已运行时使用)
若应用已通过 Run ‘app’ 启动,可以附加调试器而无需重启:
- 在菜单栏选择 Run → Attach Debugger to Android Process
- 在弹出的进程列表中找到并选择当前应用包名(
cn.edu.sziit.android.debugdemo) - 点击 OK,调试器将附加到正在运行的进程
两种方式的区别:
Debug 'app'会重新冷启动应用,适合初次调试;Attach 不重启,适合在应用运行到特定状态后才需要调试的场景。
进入调试会话后,底部会出现 Debug 工具窗口
触发断点
无论你使用哪种方式进入调试会话,后续操命中断点的作一致:
- 在设备(或模拟器)上点击 第二步:触发断点(断点调试实验) 按钮
- 程序进入
DebugLab.runDemo()并命中断点,自动暂停 - 编辑器当前执行行会高亮显示
若程序没有在断点处暂停,请先检查:
- 当前是否点击了 Debug ‘app’ 或已成功附加调试器
- 断点是否为红色实心圆点(灰色表示未生效)
- 断点所在代码是否被实际执行到
✅ 预期效果:程序暂停在断点处,底部出现 Debug 窗口。
5.1 Step Into(进入函数)
在 calculateTotal(...) 调用行点击 Step Into:
- 执行位置进入
calculateTotal()方法体 - Call Stack 新增一层方法调用
5.2 Step Over(越过函数)
在 val discounted = applyDiscount(...) 行点击 Step Over:
- 当前行会执行
- 执行位置移动到下一行
- 不进入
applyDiscount()内部
5.3 Step Out(跳出函数)
先用 Step Into 进入 applyDiscount(),再点击 Step Out:
- 直接执行完当前方法剩余语句
- 返回调用该方法的位置
5.4 Resume Program(继续运行)
点击 Resume Program:
- 程序继续执行
- 会停在下一个断点或直接执行结束
✅ 预期效果:能够区分三种单步操作的行为差异。
5.5 调试按钮速查
| 按钮 | 英文名称 | 作用 |
|---|---|---|
| 继续 | Resume Program | 继续运行到下一个断点或程序结束 |
| 越过 | Step Over | 执行当前行,不进入函数内部 |
| 进入 | Step Into | 进入当前行调用的方法内部 |
| 跳出 | Step Out | 执行完当前方法并返回调用位置 |
6.1 查看局部变量
程序暂停后,打开 Variables 面板,重点观察:
pricesdiscountRatesumpricediscounted
每点击一次单步按钮,立即对比变量值变化。
6.2 添加观察表达式
在变量上右键选择 Add to Watches,添加:
sumdiscounted
✅ 预期效果:可以准确指出“哪一行代码导致了哪个变量值变化”。
7.1 断点不命中
- 先确认使用的是 Debug ‘app’ 而不是 Run ‘app’
- 重新点击断点一次(删除)再点击一次(重新添加)
- 点击 Rerun 重新启动调试会话
7.2 看不到变量
- 确认程序当前处于暂停状态(命中断点)
- 在 Debug 窗口切换到 Variables 标签
- 若变量在当前作用域不可见,先用 Step Into 进入对应函数
7.3 单步后代码跳转异常
- 优先使用 Step Over 观察主流程
- 遇到库函数或系统函数,可用 Step Out 返回业务代码
8.1 提交内容
提交以下内容:
- 断点命中截图(显示当前高亮执行行)
Step Into进入applyDiscount()的截图Variables或Watches变量变化截图- 分别用 1 句话说明:
Step Over、Step Into、Step Out的区别
8.2 评分建议(100 分)
- 断点添加与命中:30 分
- 单步控制操作:40 分
- 变量观察与说明:30 分