跳到主要内容

网络与数据层

分层职责

模块放什么不放什么
core:networkAPI 接口、DTO、mapper、拦截器、OkHttp/Retrofit 装配Compose、ViewModel
core:databaseEntity、DAO、Room Database、schema业务 UI 状态
core:datastoreToken、Admin Token、端点、用户偏好业务列表缓存
core:model跨层 domain 模型Wire 专用字段细节(除非刻意共享)
core:dataRepository 接口 + OfflineFirst / Network 实现直接暴露 DTO 给 UI

UI 与 ViewModel 只依赖 Repository 与 model

Offline-first 请求节奏

以设备列表为例(OfflineFirstDevicesRepository):

  1. 观察
    observeDevices(organizationId): Flow<List<Device>>
    ← Room DeviceDao.observeDevices
  2. 刷新
    refreshDevices(...): AppResult<DevicesPage>
    ← Retrofit DevicesApi → 映射 → cacheDevices 写入 Room
  3. UI 一直收集 Flow;刷新成功后列表自动更新

写操作(创建、更新、启停)同样:调 API → 更新缓存 → 返回 AppResult

UI ──refresh──► Repository ──Retrofit──► API
▲ │
│ ▼
└──observe Flow── Room / 其它本地源

结果类型

网络与可失败操作用 AppResultcore:common)表达成功/失败,避免到处 try/catch 冒泡到 UI。
展示给用户的文案优先用后端 ErrorResponse.error.messagecode / details 留给诊断或 debug。

鉴权与 401

组件行为
AuthInterceptor附加 Bearer access token(进程内缓存,必要时回源 DataStore)
TokenAuthenticator401 时 单飞 refresh;并发请求复用新 token
Refresh 自身 401不再递归刷新;清空本地会话
AdminTokenInterceptor仅 admin 路径附加 X-Admin-Token

登出 / refresh 失败后,导航应回到 Auth 图(由 app 层会话观察驱动)。

JSON 与 DTO

  • 新网络模型优先 kotlinx.serialization + 生成序列化器
  • 单例 JsonignoreUnknownKeys = true 等(见 core:network 实现)
  • DTO 留在 network 层;经 mapper 变成 core:model 再给 Repository 外溢
  • 不要把 Retrofit 接口塞进 feature 模块

Room 缓存范围(概览)

参考架构文档中已缓存的域(会演进):

  • Dashboard overview
  • Devices、Organizations
  • Telemetry latest metrics
  • Alert / Automation rules、Notification targets
  • System build version

不进 Room: access/refresh/admin token、设备一次性 secret、bootstrap token 等(见 安全与密钥)。

改表结构时遵循 Room 迁移与 schemas/ 导出约定,避免只改 Entity 导致升级崩溃。

分页

  • 列表优先走后端 分页 / 批量 API,禁止「每行一个请求」
  • 合适时用 Paging 3Pager / PagingSource / RemoteMediator 藏在 data 层
  • 对外暴露 Flow<PagingData<…>>,UI 用 Paging Compose
  • 仅当 API 形态实在无法用 Paging 时,才在 ViewModel 谨慎处理游标;并写清原因

动态 Base URL

  1. 默认:BuildConfig.API_BASE_URL(可被 -PapiBaseUrl 覆盖)
  2. 运行时:Settings 写入 DataStore
  3. DynamicBaseUrlInterceptor 在请求时应用规范化后的 URL

本地开发覆盖方式见 本地开发

扩展一条新 API 的推荐顺序

  1. 对照后端 OpenAPI / 契约
  2. core:network 增加 DTO + API 方法 + mapper
  3. 若需离线:Entity/DAO + 迁移
  4. core:data 增加 Repository 方法(接口 + 实现)
  5. feature ViewModel 只调 Repository
  6. 单测覆盖 Repository 或 ViewModel 关键路径

自检

  • UI 层无 Retrofit/OkHttp/Room 类型
  • 有缓存的屏先 observe 再 refresh
  • 401 路径可解释(刷新或登出)
  • 错误展示用 message,不把 details 甩给普通用户
  • 无 N+1 列表请求

下一步:安全与密钥