Android 依賴注入 (Dependency Injection)
依賴注入 (Dependency Injection, DI) 這個名詞聽起來很嚇人,但其實概念非常簡單。
什麼是依賴 (Dependency)?
如果 Car 類別需要 Engine 類別才能運作,我們就說 Car 依賴 於 Engine。
沒用 DI 的寫法
Car 自己負責製造 Engine。
class Engine {
fun start() { ... }
}
class Car {
// Car 自己在這個類別內部 "new" 了一個 Engine
private val engine = Engine()
fun drive() {
engine.start()
}
}
fun main() {
val car = Car() // 我們只需要建立 Car,它自己會搞定 Engine
car.drive()
}
缺點:
- 耦合度高 (Tight Coupling):
Car與Engine綁死了。如果我想換成ElectricEngine,我必須修改Car的程式碼。 - 難以測試:做單元測試時,我無法把
Engine換成假的MockEngine,因此無法單獨測試Car的邏輯。
使用 DI 的寫法
Car 不自己製造 Engine,而是由外面的人 (Injector) 把它注入進來。
class Car(private val engine: Engine) {
fun drive() {
engine.start()
}
}
fun main() {
// 手動注入 (Manual Injection)
val engine = Engine()
val car = Car(engine) // 從外面傳進去
car.drive()
}
優點:
- 解耦:
Car不知道Engine是怎麼來的,只要是 Engine 都能用。 - 可測試:
val mockEngine = TestEngine() // 假的引擎 val car = Car(mockEngine) // 現在我們可以驗證 car.drive() 是否正確呼叫了 engine.start()
為何需要 DI 框架 (如 Hilt/Dagger)?
手動 DI 在小專案還可以,但在大專案中:
Car 依賴 Engine, Engine 依賴 Piston, Piston 依賴 Metal...
如果你要建立一個 Car,你必須手動寫這一大串:
val metal = Metal()
val piston = Piston(metal)
val engine = Engine(piston)
val car = Car(engine)
這叫做 Boilerplate Code (樣板程式碼)。
DI 框架 (如 Hilt) 的作用就是自動幫你建立這些物件關係圖 (Object Graph)。你只需要加幾個註解 (@Inject),框架就會自動幫你 "new" 這些物件並塞進去。
小結
DI 的核心精神就是:物件所需的資源,通通由外部提供,不自己建立。這讓程式碼更靈活、更模組化。在下一章,我們將介紹 Android 官方推薦的 DI 框架:Hilt。