I am building an application for solving queastionnaires. The application has three screens: MainMenuView, QuestionnaireView and SettingsView. From the MainMenu a user can enter QuestionnaireView and SettingsView, however they cannot enter QuestionnaireView unless the userId has not been submitted in the SettingsView (I am saving the userId in SharedPreferences).
In my MainMenuViewModel I created isUserIdFilled mutableState which indicates (by checking through checkUserIdFilled()) whether the userId has been submitted.
class MainMenuViewModel constructor(val getUserId: GetUserIdUseCase) : ViewModel() {
var isUserIdFilled by mutableStateOf(false)
private set
init {
checkUserIdFilled()
}
fun checkUserIdFilled() {
if (getUserId().isNotEmpty()) {
isUserIdFilled = true
}
}
}
In the NavigationHost I am checking whether userId has been submitted and navigating to SettingsView or QuestionnaireView. The if on onQuestionnaireClick works and navigates to SettingsView if the userId has not been submitted. However, the isUserIdFilled state was not updating (the init in MainMenuViewModel is not executed again as the ViewModel is still in the backstack and is not recreated) and I was redirected to SettingsView all the time (unless I restarted the app). So I added the call to checkUserIdFilled() in the NavHost. However, I don't like this approach as it changes the state from the Composable function.
@Composable
fun MyNavHost(navController: NavHostController, modifier: Modifier = Modifier) {
NavHost(
navController = navController,
startDestination = Screen.MainMenu.name,
modifier = modifier
) {
composable(Screen.MainMenu.name) {
val mainMenuViewModel = hiltViewModel<MainMenuViewModel>()
MainMenuView(
onQuestionnaireClick = {
// Is there a better way to do this and avoid the below call?
mainMenuViewModel.checkUserIdFilled()
if (mainMenuViewModel.isUserIdFilled)
navController.navigate(Screen.Questionnaire.name)
else {
navController.navigate(Screen.Settings.name)
}
},
onSettingsClick = { navController.navigate(Screen.Settings.name) },
mainMenuViewModel = mainMenuViewModel
)
}
composable(Screen.Questionnaire.name) {
val questionnaireViewModel = hiltViewModel<QuestionnaireViewModel>()
QuestionnaireView(questionnaireViewModel)
}
composable(Screen.Settings.name) {
val settingsViewModel = hiltViewModel<SettingsViewModel>()
// userId is submitted and saved to SharedPreferences here
SettingsView(settingsViewModel::onSubmitUserId, settingsViewModel)
}
}
}
Is there a better way to do this? How to update isUserIdFilled from the SettingsViewModel once the userId is submitted in a clean way?