鸿蒙 白屏问题
This commit is contained in:
203
CHANGELOG.md
203
CHANGELOG.md
@@ -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: 去掉 const,statusBarColor/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设为14,Drift读取后认为数据库已是最新版本,跳过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数据库适配 + 通知初始化修复
|
||||
|
||||
Reference in New Issue
Block a user