【问题标题】:PIN screen not displayed when app comes back to foreground应用程序返回前台时不显示 PIN 屏幕
【发布时间】:2021-09-09 13:46:52
【问题描述】:

我正在 Jetpack Compose 中构建一个应用程序,用户可以在其中设置将存储在 sharedPrefs 中的个性化 PIN。每次应用程序回到前台(并且用户已经预先设置了一个 PIN),应用程序应该打开“输入 PIN”屏幕。在应用启动时,一切正常,并提示用户输入他们的 PIN,但一旦应用进入后台然后返回前台,“输入 PIN”屏幕将不再显示。

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(...) {...}
    }
}

我在调试过程中检查过 MainActivity 中的一切工作正常,但在尝试获取相应 Composable 的值时似乎存在问题。具体来说,

LaunchedEffect(isPinRequired){
   if (shouldOpenPinScreen) navController.navigate(Route.Pincode.route)
}

不再调用,导航到Route.Pincode.route 也不会触发。用LaunchedEffect(Unit) 替换LaunchedEffect(isPinRequired) 也没有帮助。有人对我如何解决这个问题有任何想法吗?

【问题讨论】:

    标签: android kotlin android-jetpack-compose android-jetpack-navigation


    【解决方案1】:

    问题在于以下几行:

    val shouldOpenPinScreen by remember {
        mutableStateOf(isPinRequired)
    }
    

    shouldOpenPinScreen 修复了isPinRequired 的第一个值,并且不会使用新值进行更新。您可以将isPinRequired 作为键传递给remember,在这种情况下,变量将被更新。但是我一般看不出有这个变量有什么意义,如果它总是和isPinRequired一样,你可以删除它并用isPinRequired替换它。

    【讨论】:

    • 谢谢,我删除了shouldOpenPinScreen。不幸的是,PIN 屏幕仍未显示。我在调试过程中注意到val pinState = openPinScreen.collectAsState() 仅在应用程序启动时执行。你知道我怎样才能改变这条线,让它每次都被触发吗?
    • @masterR0shi collectAsState 将在每次openPinScreen 值更改时触发重组。尝试将 print 添加到onResume,以确保在设置之前openPinScreen.valuefalse,之后是true
    猜你喜欢
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多