<@UJBPFB3SN>, Since Nav3's `NavBackStack` really ...
# compose-android
a
@Ian Lake, Since Nav3's
NavBackStack
really is just a
List<T>
, I always wonder if it could be part of the Dependency Graph so it could be injected to like a
ViewModel
. But if I do add it to the graph, same with this implementation here, I now lose the ability to restore the state of the
NavBackStack
. I just wonder whats the advise here? Should it be part of the DI or should it stack within the compose scope?
a
> I now lose the ability to restore the state of the
NavBackStack
. You don't. You can use something like this to save/restore the back stack.
Copy code
@Provides
@ActivityScoped
fun provideBackStack(
    @ActivityContext context: Context,
): BackStack {
    val activity = context as ComponentActivity
    val backStack = activity.savedStateRegistry.consumeRestoredStateForKey(KEY)?.let {
        // Restore back stack
    } ?: BackStack()
    activity.savedStateRegistry.registerSavedStateProvider(KEY) {
        SavedState().apply {
            // Save back stack
        }
    }
    return backStack
}
a
thats interesting.. thanks @Albert Chang
@Albert Chang, wouldn't this scope the instance to the activity? If the BackStack is getting injected inside a view model, would that be a problem? the viewmodel could likely outlast the activity lifecycle, wouldn't the viewmodel be referencing an old instance in cases like configuration change?
a
Personally I just disable activity recreation for all config changes, but yeah, that can be a problem for apps that don't. In that case, you can use a view model to hold the back stack:
Copy code
@Provides
@ActivityScoped
fun provideBackStack(
    @ActivityContext context: Context,
): BackStack {
    val activity = context as ComponentActivity
    return ViewModelProvider.create(
        activity.viewModelStore,
        activity.defaultViewModelProviderFactory,
        activity.defaultViewModelCreationExtras,
    )[BackStackViewModel::class.java].backStack
}

private class BackStackViewModel(savedStateHandle: SavedStateHandle) : ViewModel() {
    val backStack by savedStateHandle.saveable(saver = BackStack.Saver) {
        BackStack()
    }
}
a
Yeah I thought of that as well, but if I place it inside the ViewModel, its kinda of sketchy on how I would be able to inject it to another ViewModel
e
Your dependency graph (ie your component) is what should be in the VM / Retained scope.
a
@efemoney could you clarify a bit more?