久しぶりにKoin
を触ったので、メモメモ。
Koinを導入
まずKoin
を導入します。
導入については こちら を参考にしました。
build.gradle
buildscript {
// 追加
ext.koin_version = '3.1.2'
ext.kotlin_version = '1.5.20'
repositories {
google()
// なければ追加する
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:7.0.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
app/build.gradle
dependencies {
...
// 追加
implementation "io.insert-koin:koin-android:$koin_version"
}
Setup Koin v3 に記載されていますが、jcenter
の閉鎖で、koinプロジェクトのIDがorg.koin
からio.insert-koin
に変更されたとのことです。
Due to Jcenter shutdown, the koin project's maven group id was previously org.koin and is now io.insert-koin. Please check your configuration with modules below.
Application
クラスで初期化する
アプリが起動するときに最初に呼び出されるApplication
を継承したクラスで、Koin
の初期化を行います。
MyApp.kt
package com.example.sample
import android.app.Application
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
setupKoin()
}
private fun setupKoin() {
startKoin {
androidContext(this@MyApp)
modules(modules)
}
}
}
AppModule.kt
package com.example.sample
import com.example.sample.model.repository.Repository
import com.example.sample.model.repository.RepositoryImpl
import com.example.sample.ui.MainViewModel
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.module
val modules = module {
// interfaceでDIしたいときは、ジェネリクスにinterface、{ } に継承したクラスを定義する。
single<Repository> { RepositoryImpl() }
viewModel { MainViewModel() }
// AndroidViewModelを継承している場合、コンストラクタでApplicationが必要になるので「get()」を使う
viewModel { SampleViewModel(get()) }
}
モジュール宣言を別ファイルに切り出しています。各宣言については以下のような動きになります。
- single: シングルトンでモジュール宣言
- factory: モジュール宣言したクラスが必要になるたび、インスタンスを生成する
- viewModel: ViewModelのモジュール宣言で使用する
AndroidManifest.xml
<application
android:name=".MyApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true">
<activity
android:name=".ui.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
android:name
にMyApp.kt
を設定して、アプリ起動時に呼び出されるようにします。
DIする
実際にDIしてみます。
MainActivity.kt
class MainActivity : AppCompatActivity() {
// MainViewModelをDIする
private val _viewModel: MainViewModel by inject()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
...
}
}
MainViewModel.kt
class MainViewModel : ViewModel() {
private val _repository: Repository by inject(Repository::class.java)
init {
fetchRepositories()
}
private fun fetchRepositories(userName: String = "user") {
viewModelScope.launch(Dispatchers.IO) {
val result = _repository.fetchRepositories(userName)
...
}
}
}