In the Add Shopping List item screen, I have a Modal Sheet with options to take a camera snapshot or choose an image from the gallery. In this screen, I'm prepopulating Textfields either from a shared ViewModel or from Navigation arguments. The issue I'm having is that when I take a photo or pick from the gallery, sometimes the LaunchedEffect code block randomly executes and causes the TextFields to be reset. However, the LaunchedEffect always executes for the first time upon the composable entering the composition, as intended. What could be wrong with the code?
Main Activity NavHost
@Composable
fun ShoppingListApp(navController: NavHostController) {
LockScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
val sharedViewModel: SharedViewModel = hiltViewModel()
AnimatedNavHost(
navController = navController, startDestination = NavScreens.MainScreen.route,
enterTransition = { EnterTransition.None },
exitTransition = { ExitTransition.None }
) {
composable(
route = NavScreens.MainScreen.route,
) {
MainScreen(navController)
}
composable(
route = NavScreens.ShoppingListScreen.route
) {
val viewModel: ShoppingListScreenViewModel = hiltViewModel()
ShoppingListScreen(navController, viewModel, sharedViewModel)
}
composable(
route = NavScreens.AddItemScreen.route + "?id={id}&name={name}&category={category}",
arguments = listOf(
navArgument("id") {
type = NavType.LongType
defaultValue = 0L
},
navArgument("name") {
type = NavType.StringType
defaultValue = ""
},
navArgument("category") {
type = NavType.StringType
defaultValue = ""
}
)
) { entry ->
val addShoppingListScreenviewModel: AddShoppingListItemScreenViewModel = hiltViewModel()
AddItemScreen(
name = entry.arguments?.getString("name")!!,
category = entry.arguments?.getString("category")!!,
navController = navController,
addShoppingListItemScreenViewModel = addShoppingListScreenviewModel,
sharedViewModel = sharedViewModel
)
}
}
}
Shared ViewModel
class SharedViewModel: ViewModel() {
private val _item = mutableStateOf(ShoppingListItem())
private val _isEdit = mutableStateOf(false)
val item: State<ShoppingListItem>
get() = _item
val isEdit: State<Boolean>
get() = _isEdit
fun setState(stateToEdit: String, stateValue: Any?){
var item = _item.value
var isEdit = _isEdit.value
when (stateToEdit) {
"ShoppingListItem" -> item = stateValue as ShoppingListItem
"IsEdit" -> isEdit = stateValue as Boolean
}
_item.value = item
_isEdit.value = isEdit
}
}
Add Item Composable
@Composable
fun AddItemScreen(
navController: NavHostController,
addShoppingListItemScreenViewModel: AddShoppingListItemScreenViewModel,
sharedViewModel: SharedViewModel,
name: String = "",
category: String = "",
) {
val shoppingListItem = sharedViewModel.item.value
LaunchedEffect(Unit) {
if (name.isNotEmpty() && category.isNotEmpty()) {
addShoppingListItemScreenViewModel.setStateValue("Name", name)
addShoppingListItemScreenViewModel.setStateValue("Category", category)
} else {
addShoppingListItemScreenViewModel.setStateValue(
"ShoppingListItem",
shoppingListItem
)
}
}
...
}