Manual Dependency Injection
When creating a simple app making use of the AbstractSavedStateViewModelFactory
to manually inject dependencies, this section showcases a sample using that.
ViewModel
A paired down version of the ViewModel
for this sample is shown below:
class MainViewModel(
savedStateFlowHandle: SavedStateFlowHandle,
private val newsDataSource: NewsDataSource
) : ViewModel() {
private val query: SavedStateFlow<String> =
savedStateFlowHandle.getSavedStateFlow(viewModelScope, "main-viewmodel-query-key", "")
init {
observeQuery()
}
fun updateQuery(query: String) {
this.query.value = query
}
private fun observeQuery() {
viewModelScope.launch {
query.asStateFlow()
.flatMapLatest { query ->
newsDataSource.fetchQuery(query)
}
.collect { results ->
//TODO update state
}
}
}
}
The full version of this ViewModel
can be found here.
ViewModel Factory
Now to actually create an instance of the ViewModel
and provide it an instance of SavedStateFlowHandle
, create a factory class that extends AbstractSavedStateViewModelFactory
and make use of the extension function SavedStateHandle.toSavedStateFlowHandle()
.
class MainViewModelFactory(
owner: SavedStateRegistryOwner,
defaultArgs: Bundle? = null
) : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
override fun <T : ViewModel?> create(
key: String,
modelClass: Class<T>,
handle: SavedStateHandle
): T {
return MainViewModel(handle.toSavedStateFlowHandle(), NewsRepository) as T
}
}
Grabbing a Reference to ViewModel
Finally an instance of a ViewModel
can be grabbed from the view using the by viewmodels { }
delegation function and passing it an instance of the factory.
class MainActivity : ComponentActivity() {
private val viewModel: MainViewModel by viewModels {
MainViewModelFactory(this)
}
}
Resources
Suggestion
Manual dependency injection is great for small apps and for understanding the basic concept, however it can lead to writing a lot of boiler plate code creating ViewModel
factory classes. To help reduce the amount of boiler plate, you can move onto the next section to see how a dependency injection framework like Hilt can be used with SavedStateFlow
.