Android中Object类与Hilt @Singleton类的选择及优势分析
先看你给出的两个代码示例:
object A { ... }
@Singleton class B { ... }
你觉得二者技术层面作用相同,其实只是都能实现单例效果,但Hilt的@Singleton在依赖注入体系里的灵活性、可维护性,是普通object单例远远比不了的,具体优势如下:
依赖可注入,支持测试替换:object单例的内部依赖只能硬编码初始化,比如
object A { val repo = Repo() },没法通过DI框架动态注入不同实现;而@Singleton修饰的B可以通过构造函数接收依赖,比如@Singleton class B @Inject constructor(private val repo: Repo),Hilt会自动帮你注入Repo的实例。测试时还能轻松替换成MockRepo,不用改业务代码,这对单元测试来说是刚需。生命周期可绑定、可定制:object单例是JVM进程级别的,从APP启动到进程销毁一直存在;但Hilt的
@Singleton默认绑定到Application生命周期,要是做多进程APP,Hilt的单例会在每个进程单独初始化,避免跨进程状态共享的坑。另外你还能自定义Scope,让单例只在某个Feature模块或页面生命周期内存活,这是object单例做不到的。懒加载时机更灵活:object单例是第一次被访问时就自动初始化;而Hilt的
@Singleton默认是第一次被注入时才初始化,你也可以通过@EarlyEntryPoint注解提前触发初始化,适配不同的业务场景。代码解耦,符合DI规范:用
@Singleton的话,所有依赖都由Hilt统一管理,业务代码里不会出现直接调用A的硬编码,而是通过构造函数注入依赖。哪天要把B换成其他实现,只要修改Hilt的绑定规则就行,不用改动所有调用B的地方,模块耦合度更低。
性能差异
两者在性能上几乎没有区别。object是JVM原生的单例实现,初始化速度快;Hilt的@Singleton是通过Dagger生成的高效静态代码实现的,初始化开销可以忽略不计,日常开发中完全感知不到差异。
内容的提问来源于stack exchange,提问作者Tangibleidea

