Kotlin Inject ViewModel

kotlin-inject-viewmodel is a custom annotation processor that builds on top of
kotlin-inject-anvil to provide a way to inject ViewModels similar to
Hilt and @HiltViewModel.
[!IMPORTANT]
Only the Android and iOS targets have been implemented and tested.
Desktop targets are planned and will be implemented next.
Setup
The project requires kotlin-inject
and kotlin-inject-anvil so please refer
to their respective docs for setup.
For kotlin-inject-viewmodel:
dependencies {
ksp("com.teobaranga.kotlin.inject.viewmodel:compiler:$version")
implementation("com.teobaranga.kotlin.inject.viewmodel:runtime:$version")
implementation("com.teobaranga.kotlin.inject.viewmodel:runtime-compose:$version")
}
Features
- Plugs in nicely into existing projects using Hilt wanting to migrate to kotlin-inject without requiring a different
injection strategy for ViewModels
- Compose and Activity/Fragment support
- Support all types of ViewModels, both with injected dependencies and with assisted dependencies
TODO
Usage
Given any ViewModel, add the @ContributesViewModel annotation with a scope such as anvil's AppScope.
A ViewModel factory will be generated per scope and it will known how to create all the ViewModels contributed
to that scope.
@Inject
@ContributesViewModel(AppScope::class)
class MyViewModel(val foo: Foo) : ViewModel()
Add a way to extract the generated ViewModel factory from the component.
@MergeComponent(AppScope::class)
@SingleIn(AppScope::class)
abstract class AppComponent {
@ForScope(AppScope::class)
abstract val vmFactory: ViewModelProvider.Factory
}
The factory can be used where needed to override the defaults and create ViewModels through injection.
For Compose, the standard viewModel Composable API can be used with the generated factory.
val viewModel = viewModel<MyViewModel>(
factory = (application as App).appComponent.vmFactory
)
For convenience, the runtime-compose dependency provides a simpler way to access ViewModels without repeating
the factory parameter. Provide a LocalViewModelFactoryOwner once at the top of the Composable tree then use the
injectedViewModel function to get a ViewModel using that factory.
CompositionLocalProvider(
LocalViewModelFactoryOwner provides object : ViewModelFactoryOwner {
override val viewModelFactory: ViewModelProvider.Factory
get() = (application as App).appComponent.vmFactory
}
) {
val viewModel = injectedViewModel<MyViewModel>()
}
For Activities or Fragments, you can use existing APIs from androidx.activity.viewModels or
androidx.fragment.app.viewModels, respectively.
class MyActivity : ComponentActivity() {
override val defaultViewModelProviderFactory: ViewModelProvider.Factory
get() = (application as App).appComponent.vmFactory
val myViewModel by viewModels<MyViewModel>()
}
Assisted injection is supported, eg:
For more practical examples, see the sample app.
License
Kotlin Inject ViewModel is distributed under the terms of the Apache License (Version 2.0). See the
license for more information.