常见开发问题与排障指南
约 1280 字大约 4 分钟
2026-03-20
1. 背景与目标
这篇文档用于快速定位“跑不起来、刷不出来、更新不生效”这类高频问题。
建议使用方式:先按问题类别定位,再按“现象 -> 原因 -> 排查步骤”执行。
2. 排障入口(先看树)
相关文件
├─ gradle/libs.versions.toml # 依赖版本与兼容约束
├─ app/src/main/java/com/kurosu/sleepin/data/local/SleepInDatabase.kt
├─ app/src/main/java/com/kurosu/sleepin/ui/screen/
├─ app/src/main/java/com/kurosu/sleepin/widget/
└─ docs/SleepIn-Docs/docs/dev/
├─ build-debug-windows.md
├─ data-model-room.md
├─ ui-viewmodel-compose.md
└─ widget-workmanager.md3. 构建与依赖问题
Q1: Duplicate class found 或 Cannot resolve ...
- 现象:
.\gradlew assembleDebug失败,出现类冲突或符号无法解析。 - 常见原因:新增依赖和现有 Compose/Kotlin/KSP 版本不兼容。
- 排查步骤:
- 检查
gradle/libs.versions.toml的相关版本是否成套兼容。 - 执行
.\gradlew clean后重试构建。 - 对照
build-debug-windows.md的基础环境确认 JDK 与 SDK 版本。
- 检查
4. Room 与数据库问题
Q2: Room cannot verify the data integrity
- 现象:修改 Entity 后 App 启动崩溃。
- 常见原因:数据库结构变化但版本与迁移策略未同步。
- 排查步骤:
- 检查
SleepInDatabase.kt中@Database(version = ...)。 - 开发阶段若允许清库,确认当前是否走了 destructive migration 策略。
- 检查
app/schemas/com.kurosu.sleepin.data.local.SleepInDatabase是否与改动一致。
- 检查
5. UI 状态与 Compose 问题
Q3: 数据已经写入,但界面不刷新
- 现象:数据库已有新数据,页面仍显示旧内容。
- 常见原因:ViewModel 只做一次性查询,未持续收集
Flow。 - 排查步骤:
- 检查 Repository 是否暴露
Flow。 - 检查 ViewModel 是否把流映射为
StateFlow并持续收集。 - 检查 Screen 是否使用
collectAsStateWithLifecycle()。 - 参考文档:
docs/SleepIn-Docs/docs/dev/3.business/3.ui-viewmodel-compose.md
- 检查 Repository 是否暴露
Q4: 页面重复弹窗/重复导航
- 常见原因:把副作用写在 Composable 主体,而非事件流中。
- 修复建议:使用
SharedFlow+LaunchedEffect处理一次性事件。
6. Widget 刷新问题
Q5: 小组件修改后没有更新
- 现象:改了 Widget UI 代码但桌面显示不变。
- 常见原因:没有触发刷新任务,或系统缓存了旧视图。
- 排查步骤:
- 检查是否调用
WidgetRefreshScheduler.requestImmediateUpdate(context)。 - 检查
WidgetRefreshWorker是否持续重试。 - 手动移除并重新添加小组件,排除 Launcher 缓存影响。
- 参考文档:
docs/SleepIn-Docs/docs/dev/2.architecture/5.widget-workmanager.md
- 检查是否调用
7. CSV 导入问题
Q6: 导入成功提示但无课程
- 常见原因:CSV 行被解析器判定为非法并写入错误列表。
- 排查步骤:
- 查看导入报告中的行级错误信息。
- 核对星期、节次、周次格式是否符合项目规则。
- 参考文档:
docs/SleepIn-Docs/docs/dev/3.business/4.csv-integration.md
Q7: 作息表 CSV 在编辑页导入失败
- 现象:已有作息表编辑页点击导入或调用导入逻辑后提示不支持。
- 常见原因:当前策略只允许“新建作息表”场景导入。
- 排查步骤:
- 确认当前
scheduleId是否为空(新建态)。 - 检查 UI 是否按
isEditMode显示正确按钮分支。 - 参考文档:
docs/SleepIn-Docs/docs/dev/3.business/4.csv-integration.md
- 确认当前
Q8: 作息表 CSV 报“只能导入一个作息表”
- 现象:导入时出现“CSV must contain exactly one schedule name”。
- 常见原因:同一个 CSV 文件内出现多个不同的作息表名称。
- 排查步骤:
- 检查
作息表名称/ScheduleName列是否全表一致。 - 检查是否混入了另一份作息表数据。
- 参考文档:
docs/SleepIn-Docs/docs/dev/3.business/4.csv-integration.md
- 检查
8. 通用排障顺序(建议)
- 先复现并记录最早报错日志。
- 再定位所属层(构建、Data、Domain、UI、Widget、CSV)。
- 再回到对应文档章节按步骤排查。
- 最后补充测试或最小复现,避免同类问题再次出现。
9. 上课提醒与通知权限问题
Q9: 已开启上课提醒,但没有弹出通知权限授权框
- 现象:Android 13+ 设备中,设置页开启提醒后,系统没有弹出“允许通知”对话框。
- 常见原因:
- 当前系统不是 Android 13+(低版本不会弹该权限框)。
- 用户未开启上课提醒开关,权限请求条件未命中。
- 用户曾拒绝且选择“不再询问”,系统不再自动弹窗。
- 排查步骤:
- 确认系统版本(
Build.VERSION.SDK_INT >= 33)。 - 确认设置中已开启“上课提醒”。
- 检查
MainActivity.kt是否触发RequestPermission(POST_NOTIFICATIONS)。 - 若曾“拒绝且不再询问”,到系统应用通知设置手动开启。
- 参考文档:
docs/SleepIn-Docs/docs/dev/4.feature/2.class-reminder.md
- 确认系统版本(
Q10: 已开启提醒且已授权,但课前没有收到通知
- 常见原因:
- 当前不在学期进行中(开学前/学期结束后)。
- 当天没有符合周次规则的课程(
WeekType过滤后为空)。 - 当前时间不在“课前 N 分钟到开课前”的提醒窗口。
- 同一节课通知已被去重逻辑记录。
- 排查步骤:
- 检查
CourseReminderWorker中学期周次判定与课程筛选结果。 - 检查
reminderMinutes与课程节次时间映射是否正确。 - 检查应用内上课提醒开关与系统通知开关是否都开启。
- 参考文档:
docs/SleepIn-Docs/docs/dev/4.feature/2.class-reminder.md
- 检查
更新日志
2026/5/18 12:59
查看所有更新日志
2a526-docs(readme): update screenshot layout于
