鸿蒙 白屏问题

This commit is contained in:
Developer
2026-05-18 03:07:50 +08:00
parent 702b41c29f
commit 1bca322600
36 changed files with 8094 additions and 974 deletions

View File

@@ -4,6 +4,209 @@
***
## \[6.0.0] - 2026-05-18
### 🐛 修复鸿蒙端白屏问题 — 错误可见性 + ErrorBoundary + OHOS动画守卫
> 诊断Demo 27级测试全部通过确认所有组件单独运行正常。
> 白屏根因为 Catcher2 SilentReportMode 吞掉渲染错误 + 多处动画/BackdropFilter无OHOS守卫。
> 本次修复让OHOS端错误可见、添加ErrorBoundary防白屏、所有动画加OHOS守卫。
#### 核心修复
| 修改 | 文件 | 说明 |
|------|------|------|
| Catcher2 OHOS错误可见 | `lib/main.dart` | OHOS端添加 `_OhosConsoleHandler`,替代 SilentReportMode 吞错误 |
| ErrorBoundary防白屏 | `lib/shared/widgets/app_error_boundary.dart` | 新建渲染错误边界组件,捕获异常显示错误页而非白屏 |
| RootApp ErrorBoundary | `lib/app/app.dart` | OHOS端用 AppErrorBoundary 包裹根组件,渲染异常时显示重试按钮 |
| OHOS调试日志 | `lib/app/app.dart` | XianyanApp build 时输出主题/动画/字体配置日志 |
#### OHOS动画守卫预防性修复
| 修改 | 文件 | 说明 |
|------|------|------|
| 句子卡片入场动画 | `home_page.dart` | `_SentenceCardWithSkeleton` OHOS端跳过 fadeIn+slideY+scale+shimmer |
| 骨架屏shimmer | `home_page.dart` | `_LoadingSkeletonCard` OHOS端跳过 shimmer使用静态骨架 |
| 每日推荐加载动画 | `home_daily_card.dart` | OHOS端 rotate/fadeIn/scale/shimmer 参数归零或跳过 |
| 创作卡片BackdropFilter | `quick_card_sheet.dart` | OHOS端用纯色Container替代 BackdropFilter+blur |
#### 诊断Demo v3
| 文件 | 说明 |
|------|------|
| `lib/main_ohos_diagnostic.dart` | 27级测试覆盖基础渲染(1-7)、依赖链(8-14)、深度测试(15-21)、主应用渲染模式(22-27) |
***
## \[5.19.0] - 2026-05-18
### ♻️ 重构设置Provider拆分 — 网络设置与隐私设置独立
> 从 `general_settings_provider.dart` 拆分出网络设置和隐私设置为独立子Provider
> 遵循单一职责原则,降低单文件复杂度,便于后续维护和扩展。
#### 新增文件
| 文件 | 作用 |
|------|------|
| `lib/features/settings/providers/sub/network_settings_provider.dart` | 网络设置状态管理(代理/缓存策略/WiFi自动播放 |
| `lib/features/settings/providers/sub/privacy_settings_provider.dart` | 隐私设置状态管理(应用锁/剪贴板读取/搜索历史) |
#### 拆分字段对照
| 子Provider | 字段 | 原属 |
|------------|------|------|
| NetworkSettingsState | proxyEnabled, proxyHost, proxyPort, cacheStrategyId, autoPlayWifiOnly | GeneralSettingsState |
| PrivacySettingsState | appLockEnabled, clipboardReadEnabled, searchHistoryEnabled | GeneralSettingsState |
#### 设计说明
- 两个子Provider均使用 `Notifier<State>` 模式,与现有 `GeneralSettingsNotifier` 风格一致
- 存储键名保持 `general_` 前缀不变,与原 GeneralSettingsState 的 KvStorage 键名兼容
- `NetworkSettingsState` 通过 `CacheStrategy.fromId()` 引用 `general_settings_provider.dart` 中的枚举
- `setProxyEnabled`/`setProxyHost`/`setProxyPort` 同步调用 `NetworkProxyService` 对应方法
- `setAppLockEnabled` 同步调用 `AppLockService.setEnabled()`
***
## \[5.18.0] - 2026-05-18
### 🐛 修复系统状态栏颜色与软件主题不一致
> 移动端屏幕顶部系统状态栏背景色硬编码为黑色,导致浅色模式下状态栏与软件背景色不一致。
> 同时导航栏颜色也硬编码为黑色,与主题不匹配。
#### 问题根因
1. **statusBarColor 硬编码 Colors.black**3处代码将状态栏背景色写死为黑色浅色模式下与 `#FAFAFA` 背景色冲突
2. **导航栏颜色硬编码**systemNavigationBarColor 和 systemNavigationBarDividerColor 同样写死为黑色
3. **图标亮度不跟随主题**app_shell.dart 中状态栏图标亮度固定为亮色,浅色模式下黑色背景上显示深色图标不可见
#### 修复方案
- **statusBarColor → Colors.transparent**:透明状态栏,让应用实际背景色自然透出(现代 edge-to-edge 方案)
- **导航栏颜色 → Colors.transparent**:透明导航栏,与毛玻璃底部栏配合
- **图标亮度跟随主题**:浅色模式显示深色图标,深色模式显示浅色图标
#### 修复文件清单
| 文件 | 修复内容 |
|------|---------|
| `main.dart` | 启动时 SystemUiOverlayStyle: statusBarColor/navBarColor 改透明,图标亮度默认深色 |
| `app.dart` | AnnotatedRegion: statusBarColor/navBarColor 改透明,图标亮度跟随 isDark 动态切换 |
| `app_shell.dart` | AnnotatedRegion: 去掉 conststatusBarColor/navBarColor 改透明,图标亮度跟随 ext.isDark |
### 🐛 修复 Riverpod Notifier 构造函数中使用 ref/state 导致鸿蒙端崩溃
> 鸿蒙端启动时崩溃:`Bad state: Tried to use a notifier in an uninitialized state`
> 根因:多个 Notifier 在构造函数中调用了使用 `ref`/`state` 的方法,但 Riverpod 的 Notifier
> 在构造函数执行时 `ref` 尚未初始化,只有 `build()` 被调用后 `ref`/`state` 才可用。
#### 问题根因
- **构造函数中使用 ref/state**Riverpod Notifier 的 `ref``state` 在构造函数阶段不可用
- **影响范围**8个 Notifier 存在此反模式,其中 `ToolCenterNotifier` 是当前崩溃的直接原因
#### 修复方案
- 将构造函数中的初始化逻辑移至 `build()` 方法
- 异步初始化使用 `Future.microtask()` 延迟到 `build()` 返回后执行
- `CanvasNotifier``late final` 字段初始化器使用 `ref.read()` 也移至 `build()`
#### 修复文件清单
| 文件 | Notifier | 修复内容 |
|------|----------|---------|
| `tool_center_provider.dart` | ToolCenterNotifier | 构造函数 `_loadPersistedData()`+`_initConnectivity()``build()``Future.microtask()` |
| `chat_attachment_provider.dart` | ChatAttachmentNotifier | 构造函数 `_init()``build()``Future.microtask()` |
| `search_provider.dart` | SearchNotifier | 构造函数 `_init()``build()``Future.microtask()` |
| `pomodoro_provider.dart` | PomodoroNotifier | 构造函数 `_loadRecords()``build()``Future.microtask()` |
| `auth_provider.dart` | AuthNotifier | 构造函数 `_init()``build()``Future.microtask()` |
| `chat_session_provider.dart` | ChatSessionNotifier | 构造函数 `_init()``build()``Future.microtask()` |
| `device_discovery_provider.dart` | DeviceDiscoveryNotifier | 构造函数 `Future.microtask(_init)``build()``Future.microtask(_init)` |
| `canvas_provider.dart` | CanvasNotifier | 构造函数中 `ref.read()`+初始化 → `build()` 中执行 |
***
## \[5.17.8] - 2026-05-17
### 🐛 鸿蒙端白屏修复 — 数据库Migration未执行 + INSERT OR IGNORE兼容性
> 鸿蒙端依旧白屏根因SqfliteDelegate.open()传入version=14给sqflite.openDatabase()
> 导致sqflite自动将PRAGMA user_version设为14Drift读取后认为数据库已是最新版本跳过migration
> 结果所有表从未创建。同时INSERT OR IGNORE语法也不被OpenHarmony RDB支持。
#### 白屏根因分析
1. **sqflite.openDatabase(version:14) 跳过 Migration**sqflite打开新数据库时自动执行`PRAGMA user_version=14`Drift读取版本=14=schemaVersion认为不需要创建表
2. **INSERT OR IGNORE 不支持**OpenHarmony RDB不支持`INSERT OR IGNORE`语法报syntax error
#### 修复方案
- **去掉version参数**`sqflite.openDatabase(_path)` 不传version让Drift通过`_SqfliteVersionDelegate`自行管理schema版本
- **INSERT OR IGNORE → INSERT OR REPLACE**:在`_adaptSql()`中转换OpenHarmony RDB支持REPLACE但不支持IGNORE
- **pu.isOhos替代Platform.operatingSystem**:统一使用项目封装的平台检测方法
#### 修复文件清单
| 文件 | 修复内容 |
|------|---------|
| `sqflite_delegate.dart` | 去掉`_version`字段和`openDatabase(version:)`参数添加INSERT OR IGNORE→REPLACE转换 |
| `ohos.dart` | 去掉`SqfliteDelegate(dbPath, 14)`中的version参数 |
| `native.dart` | `Platform.operatingSystem=='ohos'``pu.isOhos` |
| `app_shell.dart` | 自实现`_isOhos``pu.isOhos`;移除多余`dart:io``logger.dart`导入 |
#### 版本管理流程(修复后)
```
1. sqflite.openDatabase(_path) — 不传version数据库版本保持0
2. Drift读取 PRAGMA user_version → 0
3. Drift判断 0 < 14 → 执行 onCreate → m.createAll() → 创建所有表
4. Drift通过 _SqfliteVersionDelegate.setSchemaVersion(14) 设置版本
5. sqflite_ohos拦截 PRAGMA user_version = 14 → 使用 db.version = 14 API
```
***
## \[5.17.7] - 2026-05-17
### 🐛 鸿蒙端白屏修复 — SQL双引号标识符 + PRAGMA兼容性
> 鸿蒙端依旧白屏根因OpenHarmony RDB引擎不支持SQL双引号标识符如`"sentences"`、`"id"`
> Drift生成的SQL使用双引号包裹标识符导致所有数据库操作报`syntax error`。
> 同时`PRAGMA user_version = N`写入和`pragma_table_info(?)`虚拟表函数也不被RDB支持。
#### 白屏根因分析
1. **双引号标识符不支持**OpenHarmony RDB的`relationalStore`不支持`"table_name"`语法Drift生成的SQL全部使用双引号
2. **PRAGMA写入不支持**`PRAGMA user_version = N`在RDB中无法执行导致Drift schema版本写入失败
3. **pragma_table_info虚拟表不支持**`SELECT ... FROM pragma_table_info(?)`在RDB中无法执行导致migration中`_safeAddColumn`失败
#### 修复方案
- **SqfliteDelegate._adaptSql()**在所有SQL执行前预处理去除双引号标识符正确处理字符串值中的转义单引号
- `SELECT * FROM "sentences"``SELECT * FROM sentences`
- `INSERT INTO "sentences" ("id", "content")``INSERT INTO sentences (id, content)`
- 事务内`_SqfliteTransactionQueryDelegate`同样使用`_adaptSql()`
- **sqflite_ohos PRAGMA写入支持**:在`Database.execute()`中拦截`PRAGMA user_version = N`,使用`db.version = N` API替代
- **sqflite_ohos pragma_table_info支持**:在`Database.doQuery()`中拦截`pragma_table_info(?)`查询,转换为`PRAGMA table_info(tableName)`并在结果中筛选
#### 修复文件清单
| 文件 | 修复内容 |
|------|---------|
| `sqflite_delegate.dart` | 添加`_adaptSql()`方法去除SQL双引号标识符事务代理同样适配 |
| `Database.ets` (sqflite_ohos) | 添加`PRAGMA user_version = N`特殊处理使用db.version API |
| `Database.ets` (sqflite_ohos) | 添加`pragma_table_info(?)`查询特殊处理转换为PRAGMA table_info |
| `OhosConstant.ets` (sqflite_ohos) | 添加`SQL_PRAGMA_USER_VERSION_SET_PREFIX`常量 |
#### SQL适配示例
```
原始SQL: SELECT * FROM "sentences" WHERE "id" = ?;
适配后: SELECT * FROM sentences WHERE id = ?;
原始SQL: INSERT OR IGNORE INTO "sentences" ("id", "content") VALUES (?, ?)
适配后: INSERT OR IGNORE INTO sentences (id, content) VALUES (?, ?)
原始SQL: PRAGMA user_version = 14
适配后: db.version = 14 (使用RDB API)
原始SQL: SELECT COUNT(*) AS cnt FROM pragma_table_info(?) WHERE name = ?
适配后: PRAGMA table_info(tableName) + 结果筛选
```
***
## \[5.17.6] - 2026-05-17
### 🐛 鸿蒙端白屏修复 — Drift数据库适配 + 通知初始化修复