登录Fragment按下返回键时如何直接关闭应用
问题原因
Navigation组件默认执行navigate跳转时,只会把新页面压入返回栈,不会自动移除栈内已存在的旧页面。你登出时直接从B跳回A,B实例仍然留在返回栈中,所以在A页面按返回键时,系统会弹出栈内缓存的B页面,就出现了退回登录页后按返回键又进入用户列表的问题。
实现方案
优先使用导航配置清理返回栈的方式实现,不需要写额外拦截逻辑,兼容性最好。
1. 配置导航图跳转规则
打开项目的nav_graph.xml导航配置文件,给两个跳转Action添加栈清理参数:
- 登录成功从A跳B的Action:添加
app:popUpTo="@id/loginFragment"、app:popUpToInclusive="true"属性。跳转完成后登录页A会被移出返回栈,此时B处于栈底位置,用户在B页面按返回键会直接退出应用,不会退回登录页。 - 登出从B跳回A的Action:添加
app:popUpTo="@id/userListFragment"、app:popUpToInclusive="true"属性。跳转回登录页时会把用户列表页B完全移出返回栈,此时返回栈内仅存A页面,按返回键会直接关闭应用。
如果是代码里动态调用跳转、不需要在xml里预定义Action的场景,直接在跳转时传入NavOptions即可,登出逻辑参考如下:
// 执行Firebase登出逻辑 FirebaseAuth.getInstance().signOut() // 配置返回栈清理规则 val options = navOptions { popUpTo(R.id.userListFragment) { inclusive = true } } // 执行跳转 findNavController().navigate(R.id.loginFragment, null, options)
登录成功跳B的代码同理:
val options = navOptions { popUpTo(R.id.loginFragment) { inclusive = true } } findNavController().navigate(R.id.userListFragment, null, options)
2. 兜底拦截方案(仅适合固定双页面结构)
如果不想调整导航配置,可以直接在登录页A中拦截返回键事件,触发应用退出:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 绑定返回键回调 requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { requireActivity().finish() } }
注意:该方案仅适合只有两个Fragment的简单导航结构,如果后续新增注册、忘记密码等需要跳转到登录页的页面,会出现其他页面跳回登录页后按返回键直接退出的异常,需要额外加状态判断,维护成本更高。
内容的提问来源于stack exchange,提问作者Aamir Ansari
相关产品推荐
相关产品推荐

