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