跳转到内容

1.4 实验:调试Android程序

1.1 实验目标

本实验完成标准:

  • 能在 Android 项目中的 Kotlin 代码里添加、删除、启用和禁用断点
  • 能使用 Step OverStep IntoStep Out 控制程序执行
  • 能在 VariablesWatches 面板查看变量值变化

1.2 导入实验项目

本实验不再从空白模板新建项目,直接导入现有工程。

📦 下载实验项目压缩包(DebugDemo.zip)

请按以下顺序一次完成导入:

  1. 从资源目录获取 DebugDemo.zip,并解压到合适目录(路径避免中文和空格)
  2. 在 Android Studio 中点击 Open(或 File → Open…
  3. 选择解压后的 DebugDemo 项目根目录(包含 settings.gradle.kts 的那一层)
  4. 首次弹窗时点击 Trust Project
  5. 等待 Gradle Sync 完成(出现 BUILD SUCCESSFUL
  6. 点击一次 Run ‘app’,确认项目可正常启动

详细图文可参考《1.3 导入已有 Android 项目》

2.1 实现 printLogs() 函数

MainActivity.ktprintLogs() 函数体中填入日志代码,将姓名与学号替换为你自己的信息:

app/src/main/java/cn/edu/sziit/android/debugdemo/MainActivity.kt
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.vLog.dLog.iLog.wLog.e 五个级别日志,日志内容带有姓名和学号。


2.2 查看 Logcat 输出

  1. 打开底部 Logcat 窗口(也可通过菜单 View → Tool Windows → Logcat 打开)
  2. 在 Logcat 顶部左侧的设备选择器中,选择当前运行的模拟器
  3. 在日志过滤规则输入框中输入 package:mine tag:DebugDemo,只显示我们刚才添加的日志

package:mine 过滤出当前应用的日志(mine 是 Android Studio 内置的别名,代表当前运行的应用包)

tag:DebugDemo 过滤出我们使用 DebugDemo 作为 Tag

选择应用进程并调整日志级别
  1. 点击工具栏 Run ‘app’ 运行程序,等待应用完全启动
  2. 在设备(或模拟器)上点击 第一步:打印日志(Logcat 实验) 按钮,触发日志输出
点击触发日志输出

✅ 预期效果: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’(首次调试推荐)

  1. 点击 Android Studio 顶部工具栏 Debug ‘app’(小甲虫图标)
  2. Android Studio 会以调试模式重新安装/启动应用
点击 Debug 'app' 启动调试

方式二:Attach Debugger(程序已运行时使用)

若应用已通过 Run ‘app’ 启动,可以附加调试器而无需重启:

  1. 在菜单栏选择 Run → Attach Debugger to Android Process
  2. 在弹出的进程列表中找到并选择当前应用包名(cn.edu.sziit.android.debugdemo
  3. 点击 OK,调试器将附加到正在运行的进程
通过 Attach Debugger 进入调试

两种方式的区别Debug 'app' 会重新冷启动应用,适合初次调试;Attach 不重启,适合在应用运行到特定状态后才需要调试的场景。

进入调试会话后,底部会出现 Debug 工具窗口

调试会话中的 Debug 窗口

触发断点

无论你使用哪种方式进入调试会话,后续操命中断点的作一致:

  1. 在设备(或模拟器)上点击 第二步:触发断点(断点调试实验) 按钮
  2. 程序进入 DebugLab.runDemo() 并命中断点,自动暂停
  3. 编辑器当前执行行会高亮显示
程序暂停在断点处

若程序没有在断点处暂停,请先检查:

  • 当前是否点击了 Debug ‘app’ 或已成功附加调试器
  • 断点是否为红色实心圆点(灰色表示未生效)
  • 断点所在代码是否被实际执行到

✅ 预期效果:程序暂停在断点处,底部出现 Debug 窗口。

5.1 Step Into(进入函数)

calculateTotal(...) 调用行点击 Step Into

  • 执行位置进入 calculateTotal() 方法体
  • Call Stack 新增一层方法调用
Step Into 进入函数
Step Into 进入函数

5.2 Step Over(越过函数)

val discounted = applyDiscount(...) 行点击 Step Over

  • 当前行会执行
  • 执行位置移动到下一行
  • 不进入 applyDiscount() 内部
Step Over 越过函数

5.3 Step Out(跳出函数)

先用 Step Into 进入 applyDiscount(),再点击 Step Out

  • 直接执行完当前方法剩余语句
  • 返回调用该方法的位置
Step Into 进入函数

5.4 Resume Program(继续运行)

点击 Resume Program

  • 程序继续执行
  • 会停在下一个断点或直接执行结束
Step Into 进入函数

✅ 预期效果:能够区分三种单步操作的行为差异。


5.5 调试按钮速查

按钮英文名称作用
继续Resume Program继续运行到下一个断点或程序结束
越过Step Over执行当前行,不进入函数内部
进入Step Into进入当前行调用的方法内部
跳出Step Out执行完当前方法并返回调用位置

6.1 查看局部变量

程序暂停后,打开 Variables 面板,重点观察:

  • prices
  • discountRate
  • sum
  • price
  • discounted

每点击一次单步按钮,立即对比变量值变化。

Variables 面板查看变量值

6.2 添加观察表达式

在变量上右键选择 Add to Watches,添加:

  • sum
  • discounted
添加变量到 Watches 面板
Watches 面板查看变量值

✅ 预期效果:可以准确指出“哪一行代码导致了哪个变量值变化”。

7.1 断点不命中

  • 先确认使用的是 Debug ‘app’ 而不是 Run ‘app’
  • 重新点击断点一次(删除)再点击一次(重新添加)
  • 点击 Rerun 重新启动调试会话

7.2 看不到变量

  • 确认程序当前处于暂停状态(命中断点)
  • Debug 窗口切换到 Variables 标签
  • 若变量在当前作用域不可见,先用 Step Into 进入对应函数

7.3 单步后代码跳转异常

  • 优先使用 Step Over 观察主流程
  • 遇到库函数或系统函数,可用 Step Out 返回业务代码

8.1 提交内容

提交以下内容:

  1. 断点命中截图(显示当前高亮执行行)
  2. Step Into 进入 applyDiscount() 的截图
  3. VariablesWatches 变量变化截图
  4. 分别用 1 句话说明:Step OverStep IntoStep Out 的区别

8.2 评分建议(100 分)

  • 断点添加与命中:30 分
  • 单步控制操作:40 分
  • 变量观察与说明:30 分