I'm building an app in Jetpack Compose where users can set a personalized PIN that will be stored in sharedPrefs. Every time the app comes back to the foreground (and users have setup a PIN beforehand), the app should open the "enter PIN" screen. On app start, everything works fine and users are prompted to enter their PIN, but once the app goes into the background and then back into the foreground, the "enter PIN" screen is not shown anymore.
MainActivity
class MainActivity : ComponentActivity() {
private val openPinScreen = MutableStateFlow(false)
@Inject
lateinit var sharedPrefsRepository: SharedPrefsRepository
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val pinState = openPinScreen.collectAsState()
MyAppTheme {
MyApp(pinState.value)
}
}
}
override fun onResume() {
super.onResume()
sharedPrefsRepository.getPin()?.let {
openPinScreen.value = sharedPrefsRepository.hasSetPin()
}
}
}
fun MyApp(showPin: Boolean) {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = Route.Splash.route) {
composable(Route.Splash.route) {
SplashScreen {
navController.apply {
popBackStack()
navigate(Route.MainContent.route)
}
}
}
composable(Route.MainContent.route) {
MainContent(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
isPinRequired = showPin
)
}
}
}
MainContent.kt
fun MainContent(
modifier: Modifier,
isPinRequired: Boolean,
viewModel: MainViewModel = hiltViewModel()
) {
val navController = rememberNavController()
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
val shouldOpenPinScreen by remember {
mutableStateOf(isPinRequired)
}
LaunchedEffect(isPinRequired){
if (shouldOpenPinScreen) navController.navigate(Route.Pincode.route)
}
Scaffold(...){
NavHost(
navController = navController,
startDestination = Route.Home.route
) {
composable(...) {...}
composable(...) {...}
composable(...) {...}
}
}
I've checked during debugging that everything works fine in MainActivity but there seems to be a problem when trying to get the value to the respective Composable. Specifically,
LaunchedEffect(isPinRequired){
if (shouldOpenPinScreen) navController.navigate(Route.Pincode.route)
}
is not called anymore and navigation to Route.Pincode.route
is not triggered. Replacing LaunchedEffect(isPinRequired)
with LaunchedEffect(Unit)
also didn't help. Anyone got any ideas on how I could fix this?
The problem lays in these lines:
val shouldOpenPinScreen by remember {
mutableStateOf(isPinRequired)
}
shouldOpenPinScreen
fixes the first value of isPinRequired
and is not updated with the new value. You can pass isPinRequired
as a key to remember
, in which case the variable will be updated. But I generally don't see the point in having this variable, if it's always the same as isPinRequired
, you can probably remove it and replace it by just using isPinRequired
.