为什么需要依赖注入

Activity 里 new Retrofit、new Repository、new Database——一行 new 把三层焊死,换实现要改源码,写测试还要绕开真实网络。依赖注入的目标就是:谁需要对象,谁声明要什么,由外部容器负责造好递进来。

依赖注入的本质:把"创建依赖"和"使用依赖"分开。

这篇用 Hilt 把这套机制在安卓落地。

DI 的核心思想

面向接口编程:ViewModel 依赖一个 Repository 接口,具体是网络仓库还是本地仓库,由容器决定。这样上层不关心实现细节,更换实现对上层透明。Hilt 是安卓官方的 DI 框架,把这套自动装配做进编译期。

class NewsViewModel @Inject constructor(
  private val repo: NewsRepository
) : ViewModel()

构造函数加 @Inject,Hilt 自动把 NewsRepository 造好传进来。

接入 Hilt

第一步:Application 加 @HiltAndroidApp。第二步:需要注入的 Activity/Fragment 加 @AndroidEntryPoint。之后该组件里就能用 @Inject 拿对象。编译时 Hilt 会生成完整的依赖图。

常用注解
  • @Inject声明需要注入的依赖。
  • @Module集中提供自己造不了的对象。
  • @Singleton全局单例。
  • @HiltViewModelViewModel 注入。

@Inject 与模块提供

自己写的类,构造函数加 @Inject 即可。三方类(Retrofit、OkHttp)没法改它们源码,就在 @Module 里用 @Provides 写出如何构造。模块把这些"造不出来的对象"登记进容器。

Hilt 依赖注入示意:中央一个发光节点把周围多个模块方块串联成一张依赖关系图,连线带柔和蓝光
依赖图:中央节点串联各模块,自动装配。

作用域与生命周期

不带作用域的对象每次都新建;@Singleton 全局一份;@ActivityScoped 在 Activity 存活期间复用。Retrofit 客户端应是单例(重),而每个 ViewModel 各拿各的实例。作用域决定对象活多久。