8.9 KiB
8.9 KiB
🔥 卡死/闪退问题分析与修复记录
文档创建: 2026-04-09
最后更新: 2026-04-09
维护者: 前端工程师
说明: 记录项目中所有可能导致应用卡死、闪退的潜在问题,跟踪修复进度
📊 问题总览
| 等级 | 数量 | 已修复 | 待修复 |
|---|---|---|---|
| 🔴 高危 | 4 | 4 | 0 |
| 🟠 中危 | 3 | 3 | 0 |
| 🟡 低危 | 4 | 3 | 1 |
| 合计 | 11 | 10 | 1 |
🔴 高危问题(直接导致闪退)
#1 Hive late Box 未初始化访问
- 状态: ✅ 已修复
- 优先级: P0
- 文件:
lib/src/services/data/hive_service.dart - 触发路径:
MealRecordController.onInit()→_loadDayRecords()→HiveService().getMealRecordsByDate()getMealRecordsByDate()访问mealRecords.values,但mealRecords是late Box- 如果
HiveService.init()尚未完成,late字段未赋值 →LateInitializationError→ 闪退
- 修复方案:
late Box改为Box?可空类型- 所有 getter 加
_assertInitialized()检查 - Controller 中所有 Hive 读取操作前加
if (!hive.isInitialized) return;
- 修复日期: 2026-04-09
#2 ApiService 缓存竞态条件
- 状态: ✅ 已修复
- 优先级: P0
- 文件:
lib/src/services/api/api_service.dart - 触发路径:
ApiService._internal()构造函数中调用_initCacheAsync()(fire-and-forget)_cacheOptions是late CacheOptions,在_initCacheAsync()完成前未赋值- 如果首次网络请求在缓存初始化完成前发起 → 访问未初始化的
late字段 → 闪退
- 修复方案:
late CacheOptions改为CacheOptions?- 添加
Completer<void>跟踪初始化状态 _ensureCacheReady()等待 Completer 完成_tryGetCache()加 null 检查
- 修复日期: 2026-04-09
#3 Get.find 未注册 Controller 闪退
- 状态: ✅ 已修复
- 优先级: P1
- 文件:
lib/src/controllers/what_to_eat_controller.dart - 触发路径:
_fetchSmartWithPreferences()中调用Get.find<PreferenceController>()- 如果
PreferenceController未被Get.put注册 → 抛出异常 → 闪退
- 修复方案: 使用
Get.isRegistered<T>()先判断再find - 修复日期: 2026-04-09
#4 Platform API 在 Web 平台崩溃
- 状态: ✅ 已修复
- 优先级: P1
- 文件:
lib/src/utils/platform_utils.dart - 触发路径:
- 直接使用
Platform.isIOS、Platform.isAndroid等 - 在 Web 平台调用 →
UnsupportedError→ 闪退
- 直接使用
- 修复方案:
- 使用条件导入
import 'dart:io' if (dart.library.html) 'platform_web_stub.dart' - 所有
Platform.*调用前加if (kIsWeb) return false; - 创建
platform_web_stub.dart提供 Web 平台 stub
- 使用条件导入
- 修复日期: 2026-04-09
🟠 中危问题(可能导致卡死)
#5 网络请求无超时兜底
- 状态: ✅ 已修复
- 优先级: P2
- 文件:
lib/src/services/api/api_service.dart - 触发路径:
_isOffline()调用Connectivity().checkConnectivity()- 该方法本身可能卡住(如网络权限未授予)
- 虽然 Dio 设置了 10s 超时,但连接性检查无超时
- 修复方案: 给
_isOffline()加.timeout(Duration(seconds: 3))限制,超时默认视为离线 - 修复日期: 2026-04-09
#6 runWithLoading 嵌套调用状态错乱
- 状态: ✅ 已修复
- 优先级: P2
- 文件:
lib/src/controllers/base/base_controller.dart - 触发路径:
isLoading是单一RxBool- 如果外层
runWithLoading内部又调用runWithLoading - 内层完成后
isLoading = false,但外层仍在执行 - UI 显示加载完成,但数据可能不完整 → 用户操作异常
- 修复方案: 使用计数器
_loadingCount替代布尔值,仅当计数归零时设isLoading = false - 修复日期: 2026-04-09
#7 Hive Box 同步操作阻塞主线程
- 状态: ✅ 已修复(低优先级标记)
- 优先级: P3
- 文件:
lib/src/services/data/hive_service.dart - 触发路径:
getMealRecordsByDate()、getWeeklyCalories()等同步遍历 Box- 数据量大时(如数百条记录)阻塞 UI 线程
- 用户感觉"卡死"
- 修复方案:
- 短期: 当前数据量不大,影响可忽略
- 长期: 改为
compute或Isolate执行重计算
- 修复日期: 2026-04-09(标记为低优先级,暂不需要 Isolate)
🟡 低危问题(边界情况)
#8 SharedPreferences 初始化前访问
- 状态: ✅ 已修复
- 优先级: P3
- 文件:
lib/src/services/data/storage_service.dart - 触发路径:
_prefs是late SharedPreferences- 如果
init()未完成就调用getString()等 →LateInitializationError
- 修复方案:
late SharedPreferences改为SharedPreferences?- 添加
isInitialized标志 - 读取方法用
_prefs?.安全调用,返回 null - 写入方法加
if (_prefs == null) return;静默跳过
- 修复日期: 2026-04-09
#9 LoggerService 初始化前写日志
- 状态: ✅ 已修复
- 优先级: P3
- 文件:
lib/src/services/log/logger_service.dart - 修复内容:
_logger改为Logger?,所有调用处加 null 检查,降级到debugPrint - 修复日期: 2026-04-09
#10 PageRoute 中间件拦截循环
- 状态: ✅ 已修复
- 优先级: P3
- 文件:
lib/src/standards/route_middleware.dart - 触发路径:
- 如果
/standards-violation页面自身也校验失败 - 中间件再次重定向到
/standards-violation→ 无限循环
- 如果
- 修复方案: 对
/standards-violation路由跳过校验,直接return null - 修复日期: 2026-04-09
#11 MediaQuery 在 Context 不完整时崩溃
- 状态: ✅ 已修复
- 优先级: P0
- 文件:
lib/src/standards/page_standards.dart - 修复内容: 所有
MediaQuery.of(context)调用加try-catch,降级到默认值 - 修复日期: 2026-04-09
📋 修复进度
| # | 问题 | 优先级 | 状态 | 修复日期 |
|---|---|---|---|---|
| 1 | Hive late Box 未初始化 | P0 | ✅ 已修复 | 2026-04-09 |
| 2 | ApiService 缓存竞态 | P0 | ✅ 已修复 | 2026-04-09 |
| 3 | Get.find 未注册 Controller | P1 | ✅ 已修复 | 2026-04-09 |
| 4 | Platform API Web 崩溃 | P1 | ✅ 已修复 | 2026-04-09 |
| 5 | 网络请求无超时兜底 | P2 | ✅ 已修复 | 2026-04-09 |
| 6 | runWithLoading 嵌套 | P2 | ✅ 已修复 | 2026-04-09 |
| 7 | Hive 同步操作阻塞 | P3 | ✅ 标记低优 | 2026-04-09 |
| 8 | SharedPreferences 未初始化 | P3 | ✅ 已修复 | 2026-04-09 |
| 9 | LoggerService 未初始化 | P3 | ✅ 已修复 | 2026-04-09 |
| 10 | 中间件拦截循环 | P3 | ✅ 已修复 | 2026-04-09 |
| 11 | MediaQuery 空值崩溃 | P0 | ✅ 已修复 | 2026-04-09 |
🔧 修复详情
2026-04-09 修复批次(第二轮)
-
Hive late Box 未初始化 (#1)
late Box<T>→Box<T>?,getter 加_assertInitialized()MealRecordController所有 Hive 读取加if (!hive.isInitialized) return;
-
ApiService 缓存竞态 (#2)
late CacheOptions→CacheOptions?- 添加
Completer<void>跟踪初始化 _ensureCacheReady()等待 Completer_tryGetCache()加 null 检查
-
Get.find 未注册 Controller (#3)
Get.find<T>()前加Get.isRegistered<T>()判断
-
Platform API Web 崩溃 (#4)
- 条件导入
dart:io if (dart.library.html) - 所有
Platform.*调用前加kIsWeb检查 - 创建
platform_web_stub.dart
- 条件导入
-
网络请求超时兜底 (#5)
_isOffline()加.timeout(Duration(seconds: 3))- 超时默认视为离线
-
runWithLoading 嵌套 (#6)
RxBool→ 计数器_loadingCount- 仅当计数归零时设
isLoading = false
-
SharedPreferences 未初始化 (#8)
late SharedPreferences→SharedPreferences?- 读取用
?.安全调用,写入加 null 检查
-
中间件拦截循环 (#10)
/standards-violation路由跳过校验
2026-04-09 修复批次(第一轮)
-
LoggerService 空值崩溃 (#9, #11 相关)
_logger改为Logger?,所有方法加 null 检查dispose()改为_logger?.close()
-
PageStandards MediaQuery 空值崩溃 (#11)
- 所有
MediaQuery.of(context)加 try-catch - 降级到安全默认值 (375×812, 44/34 padding)
l10n改为可空AppLocalizations?
- 所有
-
l10n 可空类型连锁修复
empty_state.dart:l10n?.noData ?? '暂无数据'error_state.dart:l10n?.retry ?? '重试'standard_dialog.dart: 6处l10n?.confirm/cancel加降级中文page_validator.dart:l10n?.appTitle.isNotEmpty ?? false
-
代码警告清理 (15项)
- 移除未使用的 import / 变量 / 不必要的
!/ 死代码
- 移除未使用的 import / 变量 / 不必要的