mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-28 14:20:47 +08:00
4.9 KiB
4.9 KiB
AtomUI 异步加载架构
异步加载系统为搜索类和展开类 Control 提供共享的请求时序、取消、超时和去重模型。公共协调器由
AtomUI.Controls.Shared 拥有,具体 Control 负责触发加载、投射 UI 状态和应用成功结果。
使用方式见 异步加载使用指南。
设计原则
- 搜索覆盖与节点展开是两种不同并发模型,不使用一个可配置巨型协调器表达。
- 协调器只拥有请求时序,不直接修改 Control、集合或 UI 状态。
- 所有调用都产生结构化终态,不以异常、null 或回调顺序表达结果。
- timeout、外部取消、搜索覆盖和 loader fault 必须保持可区分。
- 请求完成后由 Control 在正确线程更新状态和数据。
- detach、owner 变化和 Control 释放必须具有明确取消路径。
公共模型
AsyncLoadStatus 定义五种终态:
| 状态 | 语义 |
|---|---|
Success |
loader 返回有效结果 |
Cancelled |
外部取消或 owner 生命周期结束 |
TimedOut |
请求超过配置的总时限 |
Faulted |
loader 抛出非取消异常 |
Skipped |
搜索请求被更新请求覆盖,旧结果不得发布 |
AsyncLoadOutcome<TResult> 保存 Status、可选 Result 和可选 Error,并提供对应状态快捷属性。
TResult 为引用类型;Success 必须携带非空结果,Faulted 才携带原始异常。
搜索协调器
AsyncSearchLoadCoordinator<TContext, TResult> 面向高频输入:
- 每次调用取消前一个进行中的搜索。
DebounceInterval延迟 loader 启动;延迟期间被替换的调用返回Skipped。Timeout从LoadAsync调用开始计时,包含 debounce。TContext允许 null,支持空搜索或清空输入场景。Cancel()结束当前搜索,但不拥有 Control 的 loading 属性。
只有最新请求能够发布结果。旧请求即使底层 loader 忽略取消并最终返回,也不能越过请求版本边界覆盖新状态。
展开协调器
AsyncExpandLoadCoordinator<TContext, TResult> 面向树和级联节点:
- 通过 comparer 对同一 context 的在飞任务去重。
- 相同 context 的调用共享 Task 和终态。
- 不同 context 可以并发运行。
- 每个请求独立 timeout。
CancelAll()用于 Control detach、数据源替换或 owner 释放。
节点默认使用引用身份,避免两个值相等但实际属于不同树位置的对象错误共享请求。
状态所有权
User interaction
-> Control trigger
-> shared coordinator
-> loader
-> AsyncLoadOutcome
-> Control state/result projection
-> public event and collection update
- Coordinator 拥有 debounce、timeout、linked cancellation 和 in-flight task map。
- Loader 拥有外部 I/O,并必须消费 CancellationToken。
- Control 拥有
IsLoading、item loading、AsyncLoaded、公开事件和集合修改。 - 应用只消费 Control 的公开结果类型,不依赖 coordinator 实现。
搜索请求的 Skipped 不触发公开完成事件,新请求继续拥有 loading 状态。展开请求成功后是否设置 AsyncLoaded 以及
如何合并子节点由具体 Control 决定。
生命周期与线程
- Search coordinator 在 Control 实例生命周期内复用,避免每次输入重新创建协调对象。
- Expand coordinator 的在飞 map 在终态后移除条目,不能永久保留节点。
- detach、数据 owner 切换和控件释放必须调用取消入口。
- loader 可以在任意线程完成;Visual、item 属性和可观察集合更新必须回到 UI 线程。
- 超时与外部取消通过 linked token 传播,不使用额外 timer callback 修改 UI。
性能与 AOT
- 正常路径不使用反射、动态成员访问或运行时类型扫描。
- 搜索只保留当前请求状态;展开只保留在飞 context。
- 去重 comparer 在协调器构造时确定,热路径不创建 comparer。
- 结果模型和 loader 调用均为强类型泛型契约。
兼容性
- 修改状态含义、timeout 是否包含 debounce、
Skipped发布规则或同 context 任务共享语义属于行为变更。 - Control 可以暴露不同属性名和默认 timeout,但必须把终态稳定映射到自身公开结果模型。
- 新 Control 不能通过吞异常、静默 timeout 或私有 fire-and-forget Task 绕过共享终态模型。
验证要求
- 搜索 debounce 期间覆盖返回
Skipped。 - loader 已启动后,新搜索取消旧请求且旧结果不能发布。
- timeout 与外部取消映射为不同状态。
- 同一展开 context 只执行一个 loader,不同 context 可以并发。
- fault 保留原始异常且不会泄漏未观察 Task。
- detach 和 owner 切换取消在飞请求并释放 context。
- UI 状态和集合更新发生在 UI 线程。
- NativeAOT 下不依赖反射或动态代码。