【尚未完成】【Android架构底层逻辑拆解】Google官方项目NowInAndroid研究(4)数据层的设计和实现之data

闻过则喜,知过不讳,改过不惮。

这是NIA系列文章中,数据层部分的最后一篇。在这篇博客中我将首先从宏观角度纵览数据的分层设计思路,随后分析数据仓库层:core:data的实现。

数据的分层设计

采用自底向上顺序,将整个NIA项目的数据层拆分如下表。

层次 说明 对上层暴露接口
数据源Source 数据的存储方式,如服务器、数据库、文件 单例,NetworkDataSource(服务器)、XXXDao(数据库),以Bean作为函数返回
数据仓库Repository 封装底层具体存取实现,通常会组合2~3个底层接口对象 单例,XXXRepository,以Flow对象作为函数返回
领域Domain 拆分后的业务基本能力,类似"数据中台" XXXUseCase,供ViewModel使用,以Flow对象作为函数返回值
特性Feature 对应到页面粒度的ViewModel 向上传递数据,向下传递控制

按照package拆分

  • di: 通过依赖注入生成各个Repository的单例
  • model: network层的数据对象,同样会将其转换为通用的Topic、NewsResource等来使用
  • repository: 依照业务实体划分的各个Repository,对外(上层业务)暴露的主要接口,返回的数据格式为Flow
  • util: 请求监控、数据同步等工具类

di------依赖注入绑定默认的Repository

di包内部有两个类,分别是生成UserNewsResourceRepositoryinterface UserNewsResourceRepositoryModule和生成TopicsRepositoryNewsResourceRepository等的abstrace class DataModule

疑问:同样是借助Hilt注入能力自动生成单例对象,为什么使用了接口、抽象类两种不同的写法?是否可以只采用接口来实现?

是否可以只采用接口来实现?------在当前项目的场景中,这个问题的答案是肯定的。首先来学习了解下这两种方式的区别。

知识点:Hilt的两种注入方法

Hilt框架提供了抽象类、接口两种注入方式,这两种注入方式的区别其实也就是抽象类、接口之间的区别,比如抽象类可以含有属性及非抽象函数等。

特性 抽象类写法 接口写法
类类型 必须声明为 abstract class 必须声明为 interface
方法修饰符 需显式添加 abstract 关键字 方法默认抽象,无需 abstract 关键字
构造函数 可以有构造函数(但 Hilt 模块不需要) 不能有构造函数
成员变量 可声明非静态属性 不能有属性(仅支持抽象方法)
多继承 单继承(Kotlin 单继承限制) 支持多实现多个接口
代码风格 更贴近传统 Java 风格 更符合 Kotlin 简洁风格

在具体代码中,这两种写法有些微的不同。

kotlin 复制代码
// 抽象类写法(必须显式声明 abstract)
@Module
abstract class DataModule {
    @Binds
    abstract fun bindsRepo(impl: Impl): Interface
}

// 接口写法(默认抽象,无需关键字)
@Module
interface UserRepoModule {
    @Binds
    fun bindsRepo(impl: Impl): Interface // 隐式抽象
}

如果需要结合@Binds@Provides,则只能使用抽象类,因为后者依赖于完整的函数实现。

kotlin 复制代码
@Module
abstract class HybridModule {
    @Binds
    abstract fun bindInterface(impl: Impl): Interface

    @Provides
    fun provideUtility(): Utility {  // 接口无法添加此方法
        return Utility()
    }
}

如果不需要@Provides,那么使用抽象类和接口是等价的,两种写法最终都会被 Hilt 处理为相同的依赖注入逻辑,没有性能或功能上的差异。出于接口契约性编码简洁 的考虑,最佳编程实践是使用接口Interface

Repository------封装后的数据仓库

repository包内部大部分都是以XXXRepository命名的类,

Sync同步机制

相关推荐
cyforkk2 小时前
重新认识 MCP:大模型时代的“标准接口”与架构边界
架构
富贵冼中求2 小时前
从单向流到双向 RPC:Agent 通信协议的范式分叉与 ACP 协议实战拆解
设计模式·架构
XUHUOJUN3 小时前
Azure Local 2602→2606 演进全景:2604 为什么是架构转折点(2602→2606 演进与升级价值·中篇)
架构·azure local
恒拓高科WorkPlus4 小时前
BeeWorks Meet私有化视频会议:内网会议、组织架构联动与会议安全
安全·架构
adinnet20265 小时前
深度拆解企业级 Agent 架构:LangGraph + 知识图谱 + 向量检索的协同设计
人工智能·架构·知识图谱
listening7775 小时前
HarmonyOS 6.1 混沌工程实战:从“故障免疫”到“韧性架构”
华为·架构·harmonyos
晚风吹长发5 小时前
Docker使用——Docker容器及相关命令
linux·运维·服务器·docker·容器·架构
郝学胜-神的一滴5 小时前
[简化版 GAMES 104] 现代游戏引擎 02:拆解现代游戏引擎5+1层级架构,吃透引擎底层核心逻辑
c++·unity·架构·游戏引擎·图形渲染·unreal engine·系统设计
电子科技圈5 小时前
先进封装、芯粒架构和3D集成——先进异构集成亟需兼具标准化与定制化能力的互联及总线IP解决方案
tcp/ip·设计模式·架构·软件构建·代码规范·设计规范
小码哥哥6 小时前
RAG系统存储架构深度解析:异构存储统一接入、向量化索引优化与物理级数据隔离实践
架构