依赖注入 (Dependency Injection, DI) 是一种设计模式,它让一个对象不再自己创建它所依赖的其他对象,而是由外部容器或框架“注入”进来。简单说就是:“我要什么,你给我,我不 new”。
在 Android 中,依赖注入通常通过构造函数、字段或方法将依赖传入。例如 Car(engine: Engine) 而不是 Car() { engine = Engine() }。
依赖注入让代码更灵活、可测试、可维护。以下是核心优势:
| 特性 | 说明 | 中小学生比喻 |
|---|---|---|
| 🔁 解耦 | 类不负责创建依赖,只负责使用,更换实现无需修改类。 | 🎒 换文具盒不用换书包 |
| 🧪 可测试 | 轻松注入 Mock 对象,单元测试更简单。 | 🧪 用假电池测试遥控器 |
| ♻️ 复用 | 依赖可被多个消费者共享,避免重复创建。 | 📚 全班共用一本词典 |
| 🧩 清晰 | 依赖关系显式化,一目了然。 | 🗂️ 作业清单写清楚 |
没有 DI,类会变成“硬骨头”,难以替换、难以测试。尤其在大型 Compose 项目中,DI 让 UI 与业务逻辑干净分离。
手动 DI 就是自己写“工厂”或“构造器”来组装依赖。在小项目中勉强可用,但规模一大,问题就暴露了:
手动 DI 就像自己搬砖盖房子,而 Hilt 就像有了施工队和图纸 —— 省心、规范、不易塌。在 Compose 中,Hilt 配合 hiltViewModel() 让注入变得优雅。
// ❌ 手动依赖注入:每个地方都要 new,耦合严重 class Car { private val engine = Engine() // 硬编码依赖 private val battery = Battery() // 难以替换 fun start() { engine.run() } } // 测试时想用 MockEngine?必须修改 Car 内部! // 如果 Engine 又依赖 SparkPlug,手动创建更加痛苦
// ✅ Hilt 注入:清晰、可测试、自动管理
@HiltViewModel
class CarViewModel @Inject constructor(
private val engine: Engine,
private val battery: Battery
) : ViewModel() {
fun start() { engine.run() }
}
// 在 Compose 中直接使用
@Composable
fun CarScreen(viewModel: CarViewModel = hiltViewModel()) {
// ...
}