94 lines
4.4 KiB
Markdown
94 lines
4.4 KiB
Markdown
# 架构设计
|
||
|
||
## 整体架构
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────┐
|
||
│ apps/quanxue apps/品牌B apps/品牌C │ 品牌应用层
|
||
│ (16 行 main.dart) │ 只传 ShellEnvironment
|
||
├──────────────────────────────────────────────────────┤
|
||
│ web_shell_core │ 核心库
|
||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||
│ │ config │ │ engine │ │ bridge │ │
|
||
│ │ 环境配置 │ │ 兼容引擎 │ │ JS 桥接 │ │
|
||
│ └──────────┘ └──────────┘ └──────────┘ │
|
||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||
│ │ services │ │ ui │ │ testing │ │
|
||
│ │ 宿主服务 │ │ 壳层界面 │ │ 测试钩子 │ │
|
||
│ └──────────┘ └──────────┘ └──────────┘ │
|
||
├──────────────────────────────────────────────────────┤
|
||
│ CoreShellActivity (Java) │ 原生层
|
||
│ 进程隔离 · WebView 信息查询 · 深度重置 │
|
||
└──────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
## 核心流程
|
||
|
||
### 1. 启动流程
|
||
|
||
```
|
||
main() → runShellApp(env)
|
||
→ WidgetsFlutterBinding.ensureInitialized()
|
||
→ 设置屏幕方向(竖屏锁定)
|
||
→ 进入沉浸式模式
|
||
→ runApp(ShellApp)
|
||
→ Android? → WebShellPage(WebView 容器)
|
||
→ 其他? → UnsupportedPlatformPage(兜底页)
|
||
```
|
||
|
||
### 2. WebView 启动与恢复
|
||
|
||
```
|
||
WebShellPage.initState()
|
||
→ 查询 Android WebView 信息(SDK / 包名 / 版本号)
|
||
→ 生成兼容性策略(renderModes / useWideViewPort / aggressiveRecovery)
|
||
→ 创建 WebView(默认 texture 模式)
|
||
→ 首帧就绪后加载初始 URL
|
||
→ 启动看门狗计时器
|
||
→ 超时? → 切换渲染模式(hybrid)→ 深度清理 → 自动重试
|
||
→ 再超时? → 展示错误页 + 兼容性提示
|
||
```
|
||
|
||
### 3. JS Bridge 协议
|
||
|
||
```
|
||
H5 页面 Flutter 壳
|
||
│ │
|
||
│ AppShellChannel. │
|
||
│ postMessage(JSON) │
|
||
│ ──────────────────────→ │ 解析 action + payload
|
||
│ │ 执行对应 handler
|
||
│ window. │
|
||
│ __appShellReceiveResponse│
|
||
│ ←────────────────────── │ 返回 { requestId, success, data/error }
|
||
```
|
||
|
||
**支持的 Action:**
|
||
|
||
| Action | 说明 | 返回 |
|
||
|---|---|---|
|
||
| `pickImage` | 从图库选图(支持多选) | `[{name, uri, mimeType, size, dataUrl}]` |
|
||
| `captureImage` | 相机拍照 | `{name, uri, mimeType, size, dataUrl}` |
|
||
| `pickFile` | 文件选择 | `[{name, uri, mimeType, size, dataUrl}]` |
|
||
| `openExternal` | 打开外部应用 | `boolean` |
|
||
| `requestPermissions` | 请求系统权限 | `{type: statusName}` |
|
||
| `reloadPage` | 重新加载当前页面 | `true` |
|
||
| `goBack` | 返回上一页 | `boolean` |
|
||
| `closeApp` | 关闭应用 | 无(直接退出) |
|
||
|
||
## 兼容性策略
|
||
|
||
| 条件 | 渲染模式 | 恢复策略 |
|
||
|---|---|---|
|
||
| SDK ≥ 29 + WebView ≥ 113 | texture 优先 | 标准恢复 |
|
||
| SDK ≤ 28 或 WebView < 113 | hybrid 优先 | 激进恢复(2 次重试) |
|
||
| F136A 设备 | hybrid 优先 | 激进恢复 + 建议更新 WebView |
|
||
|
||
## 新增品牌
|
||
|
||
1. 创建 `flavors/品牌名.yaml`
|
||
2. 运行 `dart run tool/generate_app.dart 品牌名`
|
||
3. 脚本自动生成完整的 Flutter App 在 `apps/品牌名/`
|
||
4. 修改图标后运行 `flutter pub run flutter_launcher_icons`
|
||
5. 构建 APK:`flutter build apk --release`
|