【尚未完成】【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同步机制

相关推荐
眠りたいです12 小时前
基于脚手架微服务的视频点播系统-播放控制部分
c++·qt·ui·微服务·云原生·架构·播放器
Aczone2813 小时前
硬件(五) 存储、ARM 架构与指令系统
arm开发·嵌入式硬件·架构
闲看云起13 小时前
从 GPT 到 LLaMA:解密 LLM 的核心架构——Decoder-Only 模型
gpt·架构·llama
大咖分享课15 小时前
架构性能优化三板斧:从10秒响应到毫秒级的演进之路
性能优化·架构
echoyu.16 小时前
消息队列-初识kafka
java·分布式·后端·spring cloud·中间件·架构·kafka
程序猿阿伟16 小时前
《云原生微服务治理进阶:隐性风险根除与全链路能力构建》
微服务·云原生·架构
小马哥编程17 小时前
【软考架构】第五章 软件工程基础知识:5.1软件工程概述
架构·软件工程
一直_在路上18 小时前
Go项目实战案例解析】:以Go语言之道,构建电商高并发架构
后端·架构
一直_在路上18 小时前
Go语言并发编程架构师指南:从基础到企业级实战
后端·架构
车口18 小时前
一套代码实现表单新增,编辑和预览
架构