Koin
Di (Dependense Injection) するためにはDagger2, HiltがあるがKotlinらしくなくて使い方がやや口説くなることがあったのでIntelliJ社はKotlin専用のDIライブラリのKoinを作った。
KoinはKotlinらしく使いやすい、簡単なのでDIなんかを初めて触った素人も即座で使える。
早速やって見よう。
- build.gradle(Project: xxx) に追加
// Add Maven Central to your repositories if needed
repositories {
mavenCentral()
}
dependencies {
// Koin for Android
compile "org.koin:koin-android:$koin_version"
// Testing
testCompile "org.koin:koin-test:$koin_version"
}
- build.gradle(Module: xxx) に追加 (必要なものだけに加減する)
def koin_version = "2.1.5"
// For Android
// Koin for Android
implementation "org.koin:koin-android:$koin_version"
// Koin Android Scope features
implementation "org.koin:koin-android-scope:$koin_version"
// Koin Android ViewModel features
implementation "org.koin:koin-android-viewmodel:$koin_version"
// Koin Android Experimental features
implementation "org.koin:koin-android-ext:$koin_version"
testImplementation "org.koin:koin-test:$koin_version"
// For AndroidX
// Koin AndroidX Scope features
implementation "org.koin:koin-androidx-scope:$koin_version"
// Koin AndroidX ViewModel features
implementation "org.koin:koin-androidx-viewmodel:$koin_version"
// Koin AndroidX Fragment features
implementation "org.koin:koin-androidx-fragment:$koin_version"
// Koin AndroidX Experimental features
implementation "org.koin:koin-androidx-ext:$koin_version"
- 必要なモジュールを先に作る。
Entity->Domain(Usecase, Repository) ->Module順。
今回の例はちょっと違和感があるな。。
//-----------------------//
// package name/domain/entity/Article.kt
//-----------------------//
data class Article(
var say : String = "",
)
//-----------------------//
// package name/domain/usecase/MyUseCase.kt
//-----------------------//
class MyUseCase (
private val localRepository: LocalRepository
) {
fun sayHelloMessageShowUseCase() : String {
return localRepository.getHelloMsg()
}
}
//-----------------------//
// package name/domain/repository/LocalRepository.kt
//-----------------------//
class LocalRepository(
private val databaseModule: DatabaseModule
)
{
fun getHelloMsg() = databaseModule.getDashboard().say
}
//-----------------------//
// package name/di/DatabaseModule/DatabaseModule.kt
//-----------------------//
class DatabaseModule(
val article: Article
) {
fun getDashboard() : Article {
article.say = "Say Hello Koin"
return article
}
}
- Application ファイルを作ってstartKoinをする。
本当にシンプルすぎる。
class App : Application() {
override fun onCreate() {
super.onCreate()
startKoin {
androidContext(this@App)
modules(module {
factory { Article() }
single { DatabaseModule(get()) }
single { LocalRepository(get()) }
factory { DashboardUsecase(get()) }
viewModel { DashboardViewModel() }
})
}
}
}
- ViewModelで使う。KoinでViewModel用のモジュールを使うにはviewModelというキーワードを使わなきゃならないので注意。(viewModel { someClass() } )
普通はのInjectしたいとことにKoinComponentを継承すればできるはず。
//-----------------------//
// package name/ui/dashboard/DashboardViewModel.kt
//-----------------------//
class DashboardViewModel : ViewModel(), KoinComponent {
private val usecase: sayHelloMessageShowUseCase by inject()
private val _text = MutableLiveData<String>().apply {
value = "This is dash Fragment"
}
val text: LiveData<String> = _text
fun change() {
_text.postValue(usecase.changeText())
}
}
//-----------------------//
// package name/ui/dashboard/DashboardFragment.kt
//-----------------------//
class DashboardFragment : Fragment(), KoinComponent {
val dashboardViewModel: DashboardViewModel by viewModel()
lateinit var textView: TextView
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_dashboard, container, false)
textView = root.findViewById(R.id.text_dashboard)
dashboardViewModel.text.observe(viewLifecycleOwner, Observer {
textView.text = it
})
textView.setOnClickListener {
dashboardViewModel.change()
}
return root
}
- TestCodeはこうやる
class SampleKoinTest : KoinTest {
private val usecase: DashboardUsecase by inject<DashboardUsecase>()
@get:Rule
val koinTestRule = KoinTestRule.create {
modules(AppModules().modules)
}
@Test
fun sampleTest() {
assert("Say Hello Koin" == usecase.changeText())
}
}
- 終わり。アプリを走ってみるとDIがキチンと動く。
これは。。これは。。素晴らしいすぎる。
どんどんIntellJ社に支配されている感じがする。怖っ。。
KoinはLight weight DI ライブラリーなのでDaggerより多少の機能が足りないかもしれないがこれて十分だ。
0 comments:
댓글 쓰기