I have a composable function declared like this:
fun ScreenA(
nav: NavController,
type: SomeTypeObject,
) {
val vm = getViewModel<SomeTypeObjectViewModel>()
val state = rememberScaffoldState()
val scope = rememberCoroutineScope()
LaunchedEffect(LocalContext.current) {
when(type) {
SomeTypeObject.TYPE1 ->{
vm.updateState("1")
}
SomeTypeObject.TYPE2 -> {
//do something else
}
}
}
SomeTypeObjectViewModel contains state variable of my ScreenA like this:
var remeberVal = mutableStateOf<SomeTypeObject?>(null)
Now at some point in another composable function i use my navigationGraph to open another instance of ScreenA, so SomeTypeObjectViewModel gets recreated and remeberVal restes istelf but i want keep and reuse it when new instance of ScreenA is made.
Passing remeberVal as argument using the navigationGraph is not an option since you can only pass Strings, ints or parcelable objects which is not my case, considering that remeberVal has MutableState<SomeTypeObject?> type.
At this point my question is: Is there a way to pass remeberVal to the new instance of ScreenA or to avoid SomeTypeObjectViewModel being reinstantiated after when i re-route to ScreenA using my navigaion graph?
Thank you!
Edit:
my getViewModel() is a Koin function to injevt the ViewModel, the internal code is:
org.koin.androidx.compose ViewModelComposeExtKt.class @Composable
public inline fun <reified T : ViewModel> getViewModel(
qualifier: Qualifier?,
owner: ViewModelStoreOwner,
scope: Scope,
noinline parameters: ParametersDefinition? /* = (() → ParametersHolder)? */
): T
The navigation graph is made in something like this way:
fun MyNGraph(nav: NavHostController) {
composable(
route = Routes.CaseType1.route + "/{someParameters}/",
arguments = listOf(
navArgument("someParameters") {},
),
) { backStackEntry ->
val someParameters = backStackEntry.arguments?.getString("someParameters")
someParameters?.let { someParameters ->
ScreenA(
type = SomeTypeObject.TYPE1, // Notice here, where i change type but use the same screen
)
}
}
}
composable(
route = Routes.CaseType2.route + "/{someParameters}/",
arguments = listOf(
navArgument("someParameters") {},
),
) { backStackEntry ->
val someParameters = backStackEntry.arguments?.getString("someParameters")
someParameters?.let { someParameters ->
ScreenA(
type = SomeTypeObject.TYPE2, // Notice here
)
}
}
}
}
You are using Koin for DI, so you can just add a dependency with a broader scope than your
SomeTypeObjectViewModel
that will hold the state you want to share between different screens/composables or between different VM instances. In that way your VMs have access to a shared state (a shared state holder is usually called a Repository).Where you are configuring your Koin modules add (if you are using Koin 3.2+)
If you are using Koin < 3.2
If you also want to access the state in your composables, you can use
Flow.collectAsState()