voyager
voyager copied to clipboard
Support of `defaultArgs` in the `Screen.getViewModel()` method
Problem: I want my ViewModels to be able to receive through Hilt:
- SavedStateHandle
- Dependencies like Usecases, Repositories etc.
- Screen arguments
Solution: Default args for a savedStateHandle is one of the currently recommended ways to pass navigation arguments to the ViewModel.
I've looked into code and it seems like it would be pretty easy to add defaultArgs
support into Voyager.
So it will look something like:
@Composable
public inline fun <reified T : ViewModel> Screen.getViewModel(
viewModelProviderFactory: ViewModelProvider.Factory? = null,
defaultArgs: Bundle? = null
): T {
...
val defaultCreationExtras = if (defaultArgs != null) {
val mutableCreationExtras = MutableCreationExtras(hasDefaultViewModelProviderFactory.defaultViewModelCreationExtras)
val currentDefaultArgs = mutableCreationExtras[DEFAULT_ARGS_KEY]
if (currentDefaultArgs != null) defaultArgs.putAll(currentDefaultArgs)
mutableCreationExtras[DEFAULT_ARGS_KEY] = defaultArgs
mutableCreationExtras
} else {
hasDefaultViewModelProviderFactory.defaultViewModelCreationExtras
}
val provider = ViewModelProvider(
store = viewModelStore,
factory = factory,
defaultCreationExtras = defaultCreationExtras
)
...
}
Screen(index: Int): AndroidScreen() {
...
val viewModel: HiltDetailsViewModel = getViewModel(defaultArgs = bundleOf("index", index))
...
}
@HiltViewModel
class HiltDetailsViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle,
private val repository: SomeRepository,
private val index: Int = requireNotNull(savedStateHandle["index"])
) : ViewModel() {
...
}
I can make PR if this solution looks ok.
And by the way looks like Dagger team finally made a solution for a @AssistedInject
issue, I found it in the Dagger documentation but some APIs not released yet.