Android 應用中使用Dagger-1

簡要

看此篇前

如果還不知道Dagger是什麼,參考這篇Android Dagger基本知識與簡單測試

如果因為@Inject lateinit這行編譯錯誤,參考Android Dagger @Inject lateinit編譯錯誤?


最佳做法摘要

  • 如果有可能,請通過 @Inject 進行構造函數注入,以向 Dagger 圖中添加類型。如果沒有可能,請執行以下操作:
    • 使用 @Binds 告知 Dagger 接口應採用哪種實現
    • 使用 @Provides 告知 Dagger 如何提供您的項目所不具備的類
  • 您只能在組件中聲明一次模塊
  • 根據註釋的使用生命週期,為作用域註釋命名。示例包括 @ApplicationScope、@LoggedUserScope 和 @ActivityScope

備註:

  1. 對於 Activity,任何初始化代碼都需要放入 onCreate() 方法中。在類的構造函數中使用 @Inject 註釋(構造函數注入)。必須改為使用字段注入
  2. 字段注入只能在無法使用構造函數注入的 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的旅程,若有最新消息會通知。

廣告

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s

WordPress.com.

向上 ↑

%d 位部落客按了讚: