簡要
看此篇前
如果還不知道Dagger是什麼,參考這篇Android Dagger基本知識與簡單測試
如果因為@Inject lateinit這行編譯錯誤,參考Android Dagger @Inject lateinit編譯錯誤?
最佳做法摘要
- 如果有可能,請通過 @Inject 進行構造函數注入,以向 Dagger 圖中添加類型。如果沒有可能,請執行以下操作:
- 使用 @Binds 告知 Dagger 接口應採用哪種實現
- 使用 @Provides 告知 Dagger 如何提供您的項目所不具備的類
- 您只能在組件中聲明一次模塊
- 根據註釋的使用生命週期,為作用域註釋命名。示例包括 @ApplicationScope、@LoggedUserScope 和 @ActivityScope
備註:
- 對於 Activity,任何初始化代碼都需要放入 onCreate() 方法中。在類的構造函數中使用 @Inject 註釋(構造函數注入)。必須改為使用字段注入
- 字段注入只能在無法使用構造函數注入的 Android 框架類中使用
不知道字段注入是什麼,參考這篇Android 依賴項注入(Dependency injection)
建構方法
假設一個架構如下

首先先創建一個應用類(Application)的Dagger圖
只要運行狀態,就會存在內存內,優勢可以供給其他Android框架使用
它還允許您在測試中使用自定義應用類,從而簡化了測試
先新增一個字定義作用域ApplicationScope
@Scope
@MustBeDocumented
@Retention(value = AnnotationRetention.RUNTIME)
annotation class ApplicationScope
再來新增ApplicationComponent
由上面摘要提的,Activity任何初始化都必須放在onCreate,因此必需改為使用字段注入
所以符合無法使用構造函數注入,因此可以使用以下方法
@Component
interface ApplicationComponent {
fun inject(activity: LoginActivity)
}
接著新增以下程式碼,注意LoginViewModel只是常規類,不是 Android 架构组件 ViewModel
class LoginViewModel @Inject constructor( private val userRepository: UserRepository ) { fun testFunction() { println("into testFunction") } }
再來新增把Activity注入,如下程式碼
class LoginActivity: AppCompatActivity() { @Inject lateinit var loginViewModel: LoginViewModel override fun onCreate( savedInstanceState: Bundle? ) { //注入Activity (applicationContext as MyApplication) .appComponent.inject(this) //現在loginViewModel是可靠的,可使用 loginViewModel.testFunction() super.onCreate(savedInstanceState) } }
上面程式碼運行後,會打印 into testFunction
新增一個Model,並使用
@Module
class NetworkModule {
@Provides
fun provideInt(): Int {
return 100
}
}
再來把ApplicationComponent新增modules
@Component(modules = [NetworkModule::class]) interface ApplicationComponent { fun inject(activity: LoginActivity) //這個會對應到provideInt fun getInt(): Int }
在onCreate內新增以下,就會打印 result: 100
println("result: ${(applicationContext as MyApplication)
.appComponent.getInt()}")
這樣就把Module設定好囉!
Dagger作用域
@Singleton
@Component(modules = [NetworkModule::class])
interface ApplicationComponent {
fun inject(activity: LoginActivity)
fun getInt(): Int
}
@Singleton class UserRepository @Inject constructor( private val localDataSource: UserLocalDataSource, private val remoteDataSource: UserRemoteDataSource ) { } @Module class NetworkModule { @Singleton @Provides fun provideInt(): Int { return 100 } }
如果使用此作用域,記得ApplicationComponent是應用類創建的
因此UserRepository會始終保持在內存,直到應用被銷毀
注意:
- 使用作用域注释的模块,只能在带有相同作用域注释的组件中使用
- 使用構造函數注入(通過@Inject)時,應在類中添加作用域註釋
使用Dagger模塊時,應在@Provides方法中添加作用域註釋,如上面範例的Module

以上內容參考Android 官網
相關文章
Android 依賴項注入(Dependency injection) | Android Dagger基本知識與簡單測試 |
簡要 1. 非依賴項注入 vs 依賴項注入 2. 自動依賴項注入 | 簡要 1. Android使用Dagger前置作業 2. 基本使用方法 |
Android 應用中使用Dagger-2 | |
1. Dagger 子组件 2. 為子組件分配作用域 3. 構建 Dagger 圖的最佳做法 4. 使用 Dagger 模塊 |
訂閱Codeilin的旅程,若有最新消息會通知。
廣告