数据层
app/src/main/java/com/joker/kit/core/data 将“数据访问”从业务层中抽离出来,以仓库(Repository)模式统一包装不同来源(Network / Database / DataStore)。上层 Feature 只和仓库打交道,而不直接依赖 Retrofit、Room 或 DataStore,从而实现解耦与可替换。
模块结构
| 目录 | 说明 |
|---|---|
repository/ | 暴露给业务层使用的仓库。每个仓库可组合多个数据源(网络、数据库、本地存储等),并通过依赖注入交给调用方。 |
仓库内部再组合以下能力(分别在其他 Core 模块内定义):
- network.datasource.*:封装各个接口模块(auth/goods/userinfo…),返回
NetworkResponse。 - database.datasource.*:Room 数据访问层。
- datastore.datasource.*:首选项/kv 等本地配置存储。
仓库类型与职责
| 仓库 | 主要数据源 | 作用 |
|---|---|---|
AuthRepository | AuthNetworkDataSource | 负责登录等网络请求,输出 Flow<NetworkResponse<Auth>>。 |
AuthStoreRepository | AuthStoreDataSource (DataStore) | 统一维护 Token/登录信息的本地读写,封装“是否登录”“是否需要刷新”等判断。 |
GoodsRepository | GoodsNetworkDataSource | 商品相关接口,包含分页、详情请求。示例用途:展示如何用 Repository 接 Remix Flow;如业务不需要可删除或替换成自有模块。 |
UserInfoRepository | UserInfoNetworkDataSource | 请求用户信息的远程接口。 |
UserInfoStoreRepository | UserInfoStoreDataSource (DataStore) | 缓存/更新本地用户资料,提供便捷获取头像、昵称等能力。 |
DemoRepository | DemoDataSource (Room) | 示例数据库操作,演示如何封装增删改查及 Flow 监听;可按项目需要裁剪或替换成真实表。 |
Tip:仓库命名统一以
Repository结尾,若主要职责是本地缓存,则补充StoreRepository以示区分。
设计约定
- Flow 输出:网络/数据库接口统一返回
Flow,方便与BaseNetWorkViewModel/BaseNetWorkListViewModel对接;耗时操作默认切换到Dispatchers.IO。 - 单一入口:ViewModel 不直接依赖 DataSource,而是依赖 Repository,这样可以在仓库内部决定“先读本地再读网络”或“写入数据库后再通知 UI”。
- 依赖注入:所有仓库通过 Hilt
@Inject构造函数注入,其依赖(DataSource/DAO)也由 Hilt 提供,便于替换与测试。 - 线程与作用域:耗时操作在仓库内部切到 IO 线程,避免上层忘记处理;需要事务或组合多个源时,也在仓库层封装。
- 数据合并策略:可以在仓库中增加缓存策略,例如优先读取 DataStore/Room,再触发网络刷新;当前示例仓库保持最小实现,方便在项目扩展时参考。
使用示例
(以 GoodsRepository 为例)
kotlin
@HiltViewModel
class GoodsSearchViewModel @Inject constructor(
navigator: AppNavigator,
userState: UserState,
private val goodsRepository: GoodsRepository,
) : BaseNetWorkListViewModel<Goods>(navigator, userState) {
init { initLoad() }
override fun requestListData(): Flow<NetworkResponse<NetworkPageData<Goods>>> {
val request = GoodsSearchRequest(keyword = currentKeyword, page = currentPage, size = pageSize)
return goodsRepository.getGoodsPage(request)
}
}调用方仅需感知 GoodsRepository 的语义方法(如 getGoodsPage),无需关注 Retrofit/OkHttp 等实现细节。
如何扩展
- 新增 DataSource(可选):在
core/network、core/database或core/datastore下实现数据源,并暴露注入入口。 - 创建 Repository:在
core/data/repository中新增XXXRepository文件,引入需要的 DataSource,定义对外方法。 - 暴露方法:仓库返回
Flow/suspend函数,必要时在内部合并多源数据。 - 注入使用:在 ViewModel 或 UseCase 中通过构造函数注入仓库,即可复用。
保持这一范式,数据来源的增加/替换将不会影响上层 Feature,实现“数据层可插拔、业务层稳定”的目标。