1. karass

    Posted

    karass
Changes in title
+Daggerを使ってDI
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,139 @@
+# はじめに
+新卒で入社してから2ヶ月が立ちました。Androidに少しはなれてきたかな…
+ということで今回は、Daggerを使ってDIしていきたいと思います!
+[Dagger Hilt](https://aakira.app/blog/2020/05/dagger-hilt/)が、最近話題になってますね。
+今後、Daggerにしろ、KoinにしろDIコンテナを使うことは必須だと思うので復習していきます!
+
+※[前回](https://qiita.com/karass/items/a62d27a16b185abf47f0)の続きです
+
+
+
+# Gradle
+gradleにDaggerを追加します。
+
+```build.gradle
+ // Dagger
+ def daggerVersion = '2.26'
+ implementation "com.google.dagger:dagger:$daggerVersion"
+ kapt "com.google.dagger:dagger-compiler:$daggerVersion
+```
+# 実装
+Daggerのオブジェクトグラフに、あるクラスのインスタンスを取得する方法を追加する必要があります。
+`@Inject`アノテーションをつけることで、これを実現します。
+
+今回、
+ViewModelはRepositoryに依存していて、
+RepositoryはDatabaseに依存しています。
+
+## ViewModel
+```MainViewModel.kt
+class MainViewModel @Inject constructor(private val repository: TodoRepository) : ViewModel() {
+ val todoList = repository.allTodoList
+
+ fun insert(todo: Todo) = viewModelScope.launch {
+ withContext(Dispatchers.IO){
+ repository.insert(todo)
+ }
+ }
+```
+
+## Repository
+```TodoRepository.kt
+class TodoRepository @Inject constructor(private val todoDao: TodoDao) {
+ val allTodoList = todoDao.getAll()
+
+ @WorkerThread
+ suspend fun insert(todo: Todo) {
+ todoDao.insert(todo)
+ }
+}
+```
+
+`@Inject`アノテーションをつけることで、クラスのインスタンスの提供方法をDaggerに伝えることができました。
+
+## Module
+Interfaceなど、直接インスタンス化できないものの提供方法をDaggerに伝える必要があります。
+依存関係の定義をグループ化するには、`@Modelu`アノテーションをつけます。
+
+```DatabaseModule.kt
+@Module
+class DatabaseModule() {
+
+ @Singleton
+ @Provides
+ fun provideTodoDatabase(context: Context) =
+ Room.databaseBuilder(context,
+ TodoDatabase::class.java,
+ "database_name")
+ .build()
+
+ @Singleton
+ @Provides
+ fun provideTodoDao(todoDatabase: TodoDatabase) = todoDatabase.todoDao()
+}
+```
+
+`@Module`アノテーションをつけたクラスに、インスタンスの生成方法を`@Provides`アノテーションで実現します。
+
+
+
+
+## Component
+ComponentはDaggerがオブジェクトグラフを生成して、あるクラスのインスタンスを取得する役割があります。
+Componentを実装するには、`@Component`アノテーションをInterfaceにつけます。
+
+```AppComponent.kt
+@Singleton
+@Component(
+ modules = [
+ DatabaseModule::class
+ ]
+)
+Interface AppComponent {
+
+ @Component.Factory
+ interface Factory {
+ fun create(@BindsInstance context: Context): AppComponent
+ }
+ fun mainViewModel(): MainViewModel
+}
+```
+
+`@Singleton`アノテーションをつけることで、Singletonを実現します。
+また、ComponentにModuleクラスで定義した依存関係を追加するために、`modelu`パラメータに記述します。
+
+`@Component.Factory`アノテーションでは、Componentのインスタンス取得時に特別な処理を定義することができます。今回は、Daggerのオブジェクトグラフ生成時にContextを渡したいので、引数に`@BindsInstance`アノテーションをつけます。
+
+## Aplication
+AppComponent.Factoryを使い、AppComponentのインスタンスを取得します。
+インスタンス取得時にContextを渡します。
+
+```TodoAplication.kt
+class TodoApplication : Application() {
+ companion object {
+ lateinit var component: AppComponent private set
+ }
+
+ override fun onCreate() {
+ super.onCreate()
+ component = DaggerAppComponent.factory().create(applicationContext)
+ }
+}
+```
+
+## Activity
+```MainActivity.kt
+class MainActivity : AppCompatActivity() {
+
+ private val mainViewModel: MainViewModel by lazy {
+ TodoApplication.component.mainViewModel()
+ }
+...
+```
+これでMainActivityにMainViewModelを提供することができました。
+
+# おわりに
+Todoアプリの削除機能を実装する前に、Daggerを使ってDIしてみました!
+もし間違った記述があるなら、コメントで教えてほしいです!!!
+
+Dagger Hiltも、時間があったら触ってみようかな。