web_shell_flutter/doc/architecture.md

142 lines
5.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 架构设计
## 整体架构
```text
┌────────────────────────────────────────────────────────────┐
│ apps/aixue apps/test apps/yunxiao apps/... │ 品牌应用层
│ main.dart 只负责传入 ShellEnvironment │
├────────────────────────────────────────────────────────────┤
│ web_shell_core │ 核心库
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ config │ │ engine │ │ bridge │ │
│ │ 启动配置 │ │ 兼容引擎 │ │ JS 桥接 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ services │ │ ui │ │ testing │ │
│ │ 宿主服务 │ │ 壳层界面 │ │ 测试钩子 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
├────────────────────────────────────────────────────────────┤
│ CoreShellActivity (Java) │ 原生层
│ 进程隔离 · WebView 信息查询 · 深度重置 │
└────────────────────────────────────────────────────────────┘
```
## 配置分层
### 启动配置
启动配置负责影响首屏加载行为,当前拆成两层:
1. 本地默认启动配置:`assets/config/bootstrap.json`
2. 远程启动配置:`bootstrap_config_url`
字段示例:
```json
{
"initialUrl": "https://example.com/login",
"preferredOrientations": ["portraitUp", "portraitDown"]
}
```
### 升级配置
升级配置仅用于版本检查,不参与首页地址解析,单独由 `upgrade_config_url` 拉取。
字段示例:
```json
{
"versionName": "1.0.1",
"version": 101,
"isForce": 0,
"remark": "1. 修复已知问题",
"filePath": "https://example.com/app-release.apk",
"fileSize": 25000
}
```
## 核心流程
### 1. 启动流程
```text
main()
→ runShellApp(env)
→ WidgetsFlutterBinding.ensureInitialized()
→ 读取本地默认启动配置 bootstrapConfigAsset
→ 拉取远程启动配置 bootstrapConfigUrl可选失败走缓存
→ 合并 initialUrl / preferredOrientations
→ setupConfigUrl(upgradeConfigUrl)
→ _initializeUrls()
→ SystemChrome.setPreferredOrientations(...)
→ 进入沉浸式模式
→ runApp(ShellApp)
→ Android → WebShellPage
→ 非 Android → UnsupportedPlatformPage
```
### 2. WebView 启动与恢复
```text
WebShellPage.initState()
→ 查询 Android WebView 信息SDK / 包名 / 版本号)
→ 生成兼容性策略renderModes / useWideViewPort / aggressiveRecovery
→ 创建 WebView
→ 首帧后加载 _initialUrl
→ 同时异步执行 checkVersion(context)
→ 主帧成功 → 注入 Bridge
→ 主帧失败 → 展示 ErrorOverlay不再白屏
→ 启动超时 → 切换渲染模式 / 深度清理 / 自动重试
```
### 3. JS Bridge 协议
```text
H5 页面 Flutter 壳
│ │
│ AppShellChannel.postMessage │
│──────────────────────────────→ │ 解析 action + payload
│ │ 执行 handler
│ __appShellReceiveResponse │
│←────────────────────────────── │ 返回 { requestId, success, data/error }
```
当前支持 12 个 Action
| Action | 说明 |
|---|---|
| `pickImage` | 从图库选图 |
| `captureImage` | 相机拍照 |
| `pickFile` | 文件选择 |
| `openExternal` | 打开外部应用 |
| `requestPermissions` | 请求系统权限 |
| `reloadPage` | 重新加载当前页面 |
| `goBack` | 返回上一页 |
| `closeApp` | 关闭应用 |
| `getDeviceInfo` | 获取设备信息 |
| `getNetworkStatus` | 获取网络状态 |
| `showToast` | 展示 Toast |
| `setStatusBar` | 设置状态栏样式 |
## 兼容性策略
| 条件 | 渲染模式 | 恢复策略 |
|---|---|---|
| SDK ≥ 29 + 新版 WebView | texture 优先 | 标准恢复 |
| SDK ≤ 28 或旧版 WebView | hybrid 优先 | 激进恢复 |
| F136A 设备 | hybrid 优先 | 激进恢复 + 建议更新 WebView |
## 新增品牌流程
1. 新建 `flavors/品牌名.yaml`
2.`flavors/品牌名/` 放置品牌资源
3. 执行 `dart run tool/generate_app.dart 品牌名`
4. 生成器自动产出:
- `apps/品牌名/lib/main.dart`
- `apps/品牌名/assets/config/bootstrap.json`
- `apps/品牌名/assets/branding/*`
- Android 图标、启动页、签名配置
5. 构建 APK`cd apps/品牌名 && flutter build apk --release`