
欄位注入
【Android Hilt 依賴注入完整教學】系列文章目錄:連結
Youtube 教學頻道:HKT線上教室
今天要跟大家分享如何在 Android 專案中使用 Hilt 框架來實現欄位注入(Field Injection)的技巧。這是接續我們之前討論依賴注入(Dependency Injection)概念的進階教學。
欄位注入(Field Injection)是 Hilt 提供的一種依賴注入方式,它允許我們直接在類別的欄位上標註 @Inject 來實現注入。相較於建構子注入(Constructor Injection),欄位注入的優點是使用方式更簡單直觀,特別適合在 Android 的元件(如 Activity、Fragment)中使用。
在開始實作之前,請確保你已經完成了 Hilt 的基本設定。如果還沒有設定,可以參考我們之前的文章「在 Android 專案中導入 Hilt 依賴注入框架指南」。專案設定基礎
首先,要在 Android 專案中啟用 Hilt,我們需要:
- 建立一個應用程式類別(Application Class),並使用
@HiltAndroidApp
註解標註
@HiltAndroidApp
class MyApplication : Application()
- 在 AndroidManifest.xml 中註冊該應用程式類別
<application
android:name=".MyApplication"
...
/>
欄位注入實作步驟
1. 準備注入目標
假設我們要在 Activity 中注入一個 Product
物件,首先要做的是:
@AndroidEntryPoint
class ProductActivity : AppCompatActivity() {
@Inject
lateinit var product: Product // 注意:欄位必須是 public
}
重要說明:
@AndroidEntryPoint
註解的作用:- 標註在 Activity 類別上,讓 Hilt 知道這個 Activity 需要依賴注入
- 啟用該 Activity 的依賴注入功能
- 如果沒有此註解,Hilt 將無法為該 Activity 注入任何依賴
- 欄位可見性要求:
- 被注入的欄位必須宣告為 public
- private 欄位無法被注入的原因是 Hilt 需要直接存取該欄位
- protected 和 internal 欄位也無法被注入
- 這是因為 Hilt 在編譯時期需要生成程式碼來存取這些欄位
@Inject
註解的重要性:- 使用在要被注入的欄位上
- 告訴 Hilt 這個欄位需要被自動注入
- Hilt 會在適當的時機點(Activity 建立時)注入相應的實例
- 如果沒有此註解,該欄位將不會被 Hilt 處理
lateinit
關鍵字的必要性:- 由於依賴注入發生在物件建立之後
- 使用 lateinit 讓編譯器知道該欄位會在稍後被初始化
- 避免在建構時就需要給予初始值
- 注意:使用前要確保該欄位已被初始化,否則會拋出 UninitializedPropertyAccessException
2. 提供依賴來源
為了讓 Hilt 知道如何建立 Product
物件,我們需要在 Product
類別中標註建構子:
class Product @Inject constructor() {
fun alert() {
Log.d("Product", "Product is alerting!")
}
}
實作細節與注意事項
- 當您看到編輯器行號右側出現 consumer 符號,表示 Hilt 已經知道如何取得該物件的實例:
- 這個符號代表 Hilt 已成功建立依賴圖(dependency graph)
- 表示所有必要的依賴都已被正確設定
- 如果缺少任何依賴,編輯器會顯示錯誤提示
- 在此範例中,Hilt 會使用標註了
@Inject
的建構子來建立Product
實例: - Hilt 會在編譯時期生成必要的工廠類別(Factory classes)
- 這些工廠類別負責建立和管理物件實例
- 建構子注入是最推薦的注入方式,因為它:
- 明確表達類別的依賴關係
- 確保物件在建立時就擁有所有必要的依賴
- 有助於寫出更容易測試的程式碼
- 如果您的類別中有其他依賴(如
AlertSystem
),也需要適當地提供這些依賴的來源: - 可以透過以下方式提供依賴:
- 在依賴類別的建構子上使用 @Inject
- 在 Module 中使用 @Provides 方法
- 使用 @Binds 來綁定介面實作
- 所有的依賴都必須能被 Hilt 追蹤到其來源
- 如果有循環依賴,Hilt 會在編譯時期就發出警告
- 依賴注入的生命週期管理:
- Hilt 會根據 Component 的作用域來管理物件的生命週期
- 預設情況下,每次注入都會建立新的實例
- 可以使用作用域註解(如 @Singleton)來控制實例的重用
執行結果
執行應用程式後,您可以透過以下方式查看結果:
- 在 Android Studio 中開啟 Logcat 視窗
- 在過濾器欄位中輸入 "Product"
- 執行應用程式,您會看到類似以下的輸出:
Product: Product is alerting!
這表示:
- Hilt 成功建立了
Product
類別的實例 - 相依性注入正確運作
alert()
方法被呼叫並執行- 如果沒有看到輸出,請檢查:
- Activity 是否有正確標註 @AndroidEntryPoint
- Product 類別的建構子是否有 @Inject 標註
- Logcat 的過濾條件是否正確設為 "Product"
請注意,由於我們在 Product 類別中使用了 Log.d() 而不是 System.out.println(),所以需要在 Logcat 中過濾 "Product" 標籤來查看輸出。
後續學習
在下一篇文章中,我們將探討如何處理更複雜的依賴注入情境,特別是如何透過建構子注入(Constructor Injection)來處理多層次的依賴關係。