70 lines
4.0 KiB
Markdown
70 lines
4.0 KiB
Markdown
# 应用启动与数据加载流程
|
||
|
||
对应代码:`lib/main.dart`、`lib/core/auth/auth_service.dart`、`lib/core/referrer/referrer_service.dart`、`lib/app.dart`、`lib/features/home/home_screen.dart`。
|
||
|
||
## 总览(时序)
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant Main as main()
|
||
participant Ref as ReferrerService
|
||
participant Adj as Adjust SDK
|
||
participant Auth as AuthService.init
|
||
participant API as 后端 API
|
||
participant UI as App / HomeScreen
|
||
|
||
Main->>Adj: initSdk + attributionCallback
|
||
Main->>Ref: await init() 竞速归因并缓存 digest
|
||
Main->>Auth: init() 不 await,后台执行
|
||
Main->>UI: runApp
|
||
|
||
Auth->>Auth: delay 2s
|
||
Auth->>Ref: getReferrer() 读缓存
|
||
Auth->>API: fast_login(digest=crest)
|
||
Auth->>API: referrer(android_adjust)
|
||
Auth->>API: referrer(gg)
|
||
Auth->>API: common_info
|
||
Auth->>UI: loginComplete / isLoginComplete
|
||
|
||
UI->>API: HomeScreen._loadCategories 等 loginComplete 后
|
||
```
|
||
|
||
## 1. `main()` 中顺序(在 `runApp` 之前)
|
||
|
||
| 步骤 | 说明 |
|
||
|------|------|
|
||
| `WidgetsFlutterBinding.ensureInitialized()` | Flutter 绑定 |
|
||
| `_initAdjust()` | `Adjust.initSdk`,注册 `attributionCallback`(回调里会 `ReferrerService.receiveAttributionFromCallback`) |
|
||
| `_initFacebookAppEvents()` | Facebook `activateApp` |
|
||
| **`await ReferrerService.init()`** | 与 `getAttributionWithTimeout`、归因回调**竞速**,得到用于 **fast_login** 的 `crest`(Adjust Base64 优先,否则 Android Play Install Referrer),并写入内存缓存 |
|
||
| `SystemChrome.setSystemUIOverlayStyle` | 状态栏样式 |
|
||
| **`AuthService.init()`** | **不 await**,与 UI 首帧并行执行快速登录链路 |
|
||
| `runApp(const App())` | 构建根组件 |
|
||
| Android | `GooglePlayPurchaseService.startPendingPurchaseListener()` |
|
||
| `AuthService.loginComplete.then(...)` | 登录 Future 完成后跑谷歌支付补单 `runOrderRecovery` |
|
||
|
||
## 2. `AuthService.init()`(后台异步)
|
||
|
||
1. **固定等待 2 秒**(缓解冷启动网络未就绪)。
|
||
2. 取 **deviceId**、**sign**(MD5(deviceId) 大写)。
|
||
3. **`ReferrerService.getReferrer()`**:通常直接命中 `init()` 阶段缓存,作为 **fast_login** 的 `digest`。
|
||
4. **`POST /v1/user/fast_login`**:最多重试 3 次;成功则设置 **token**、**userId**、积分与资料字段、首次安装时 Adjust register 等。
|
||
5. **`_reportBothReferrersAndRefreshCommonInfo`**(需已登录 uid)
|
||
- 分别计算 **Adjust 专用 digest**、**Play Install Referrer(gg)**(`getAdjustReferrerDigest` / `getGgReferrerDigest`)。
|
||
- **顺序**调用两次 **`POST /v1/user/referrer`**:`accolade=android_adjust`、`accolade=gg`;**无论业务成功失败,均等待响应返回**后继续。
|
||
- 两次都结束后 **`GET /v1/user/common_info`** **一次**。
|
||
- 在 **`_saveCommonInfoToState`** 中解析 `surge` → **extConfig**(`need_wait`、`items`、`safe_area`、`lucky` 等)。
|
||
- 若 **`need_wait` 或 `items`** 相对应用前快照发生**结构性变化**,则 **`UserState.requestHomeFullReload()`**(首页完整重走分类 + 任务加载)。
|
||
6. **`finally`**:`loginComplete` 完成、`isLoginComplete = true`,去掉全屏登录等待遮罩。
|
||
|
||
## 3. 首屏 UI 与首页数据
|
||
|
||
- **`App`**:`FutureBuilder` 监听 `AuthService.loginComplete`,未完成时叠一层半透明 + `CircularProgressIndicator`。
|
||
- **`HomeScreen`**:`initState` 里 **`_loadCategories()`** 会先 **`await AuthService.loginComplete`**,再请求分类接口;根据当前 **`UserState.needShowVideoMenu`** 决定是否追加 **pets** 分类;选中非 pets 时再拉视频任务列表。
|
||
- 监听 **`UserState.needShowVideoMenu` / `extConfigItems` / `isLoginComplete`** → `setState` 刷新展示。
|
||
- 监听 **`UserState.homeReloadNonce`** → 再次 **`_loadCategories()`**,用于 **need_wait 等变化**后重新走「加载分类 → 加载任务」。
|
||
|
||
## 4. 与主页文档的关系
|
||
|
||
主页如何根据 **extConfig** 渲染分类栏与列表,见 [home.md](home.md) 与 [extConfig.md](extConfig.md)。
|