I'm using `ViewModel` as a state container for a C...
# compose
t
I'm using
ViewModel
as a state container for a Composable screen. The
ViewModel
is scoped to the nav graph via
@HiltViewModel
& `hiltNavGraphViewModel()`` . It seems that this pattern does not support assisted injection into the
ViewModel
, so I have to pass initial state to the screen's Compose function, and then pass that state into the
ViewModel
. This feels a bit uncomfortable. Am I approaching this the wrong way?
Copy code
ExerciseScreen(
    viewModel = hiltNavGraphViewModel(),
    routine = previousArguments.getParcelable(ARG_ROUTINE)
    ...
Copy code
@Composable
fun ExerciseScreen(
    viewModel: ExerciseScreenViewModel,
    routine: Routine,
) {

    val routine: Routine by viewModel.getRoutine(routine).collectAsState(initial = routine)
...
Copy code
@HiltViewModel
class ExerciseScreenViewModel @Inject constructor(
    private val appRepository: AppRepository,
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {

    fun getRoutine(routine: Routine): Flow<Routine> {
        return appRepository.getRoutines(listOf(routine.id)).map { routines -> routines.first() }
    }
    ...
Ideally, the Routine model would be @Assisted injected into the ViewModel, and then exposed to the Screen as ViewModel state. This would also make it easier to persist the Routine in the SavedStateHandle
i
If you're only passing the ID of the routine through Navigation like you're supposed to, it is already available in the SavedStateHandle: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1615161782091500?thread_ts=1615158140.089300&amp;cid=CJLTWPH7S
At that point, your app repository should always be the source of truth (using stateIn to save the last value) and you shouldn't ever be using the SavedStateHandle as a source of truth
t
Thanks, I remember reading that there was a way to access navigation arguments from the ViewModel, but I wasn't sure how. I see - the Routine was a dependency of something I wanted to persist via SavedStateHandle.
your app repository should always be the source of truth (using stateIn to save the last value)
Can you expound on that last point? I'm not sure why stateIn would be required - as the AppRepository would be persist and retrieve the latest value anyway..
i
suspending methods and collecting on a flow are not instantaneous, which means you miss having up to date data for your first composition (that's why you need to set an initial value when you collect from a regular
Flow
, but not from a
StateFlow
). If your ViewModel uses
stateIn
, then after a configuration change or when you return to that destination in Navigation Compose, your ViewModel already has the state immediately available for that first composition
t
I see, thanks!