Android 13中Fragment导航触发onPause/onResume循环致栈溢出求助
我的应用通过NavController实现Fragment间导航,核心导航代码为findNavController().navigate(R.id.step02Fragment),该逻辑在Android 13以下版本均正常运行。但在Android 13系统中,从Step05Fragment跳转至Step06Fragment时,Step05Fragment的onPause与onResume方法会无限循环执行,最终引发StackOverflow错误。其他Fragment采用完全相同的导航逻辑却未出现此问题。
依赖版本
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1" implementation "androidx.lifecycle:lifecycle-service:2.5.1" implementation "androidx.navigation:navigation-runtime-ktx:2.5.2" implementation "androidx.navigation:navigation-fragment-ktx:2.5.2" implementation "androidx.navigation:navigation-ui-ktx:2.5.2" implementation "androidx.navigation:navigation-dynamic-features-fragment:2.5.2"
Step05Fragment代码
@AndroidEntryPoint class Step05Fragment : Fragment() { lateinit var binding: FragmentStep05Binding private var initialSetup: Boolean = true private val disposable = CompositeDisposable() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { binding = FragmentStep05Binding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) arguments?.getBoolean(Constants.ENABLE_PERMISSION)?.let { initialSetup = it } setObservables() setView() } override fun onDestroy() { super.onDestroy() disposable.dispose() } private fun setObservables() { binding.btnEnable.clicks() .map { checkPermission() } .subscribe() .disposeBy(disposable) } private fun setView() { if (!initialSetup) { binding.currentStep.visibility = View.GONE } } private fun checkPermission() { if (!PermissionsUtils.isReadExternalStoragePermissionGranted(requireContext())) { requestPermission.launch(Manifest.permission.READ_EXTERNAL_STORAGE) } else { handleNavigation() } } private val requestPermission = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> if (isGranted) { handleNavigation() } else { checkPermission() } } private fun handleNavigation() { if (initialSetup) { findNavController().navigate(R.id.step06Fragment) } else { activity?.finishAffinity() } } }
Step06Fragment代码
@AndroidEntryPoint class Step06Fragment : Fragment() { lateinit var binding: FragmentStep06Binding private var initialSetup: Boolean = true private val disposable = CompositeDisposable() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { binding = FragmentStep06Binding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) arguments?.getBoolean(Constants.ENABLE_PERMISSION)?.let { initialSetup = it } setObservables() setView() } override fun onDestroy() { super.onDestroy() disposable.dispose() } private fun setObservables() { binding.btnEnable.clicks() .map { checkPermission() } .subscribe() .disposeBy(disposable) } private fun setView() { if (!initialSetup) { binding.currentStep.visibility = View.GONE } } private fun checkPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (!PermissionsUtils.isMediaLocationPermissionGranted(requireContext())) { requestPermission.launch(Manifest.permission.ACCESS_MEDIA_LOCATION) } else { handleNavigation() } } else { handleNavigation() } } private val requestPermission = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> if (isGranted) { handleNavigation() } else { checkPermission() } } private fun handleNavigation() { if (initialSetup) { findNavController().navigate(R.id.step07Fragment) } else { activity?.finishAffinity() } } }
排查思路
- 权限请求循环触发问题:Step05Fragment中,当权限被拒绝时,
requestPermission回调直接调用checkPermission(),会再次启动权限请求。Android 13对权限弹窗的生命周期处理有变化,这种重复请求可能干扰Fragment导航的正常生命周期,导致Step05Fragment无法正确转入后台,进而引发onPause/onResume循环。建议在权限拒绝时添加用户提示,而非直接重复请求。 - 导航执行时机验证:在
handleNavigation()中执行导航前,先判断Fragment状态,比如添加if (isResumed() && isAdded()),避免在Fragment生命周期不稳定时触发导航动作。 - 升级Navigation组件版本:当前使用的Navigation 2.5.2版本可能存在Android 13兼容性问题,尝试升级到2.7.x或更高稳定版本,确认是否修复了相关生命周期异常。
- 隔离Step06Fragment影响:暂时注释Step06Fragment中的权限请求逻辑,测试跳转后是否还会出现循环。如果问题消失,说明Step06Fragment的权限逻辑在Android 13下触发了异常回调,间接影响了Step05Fragment的生命周期。
- 检查导航配置:查看导航图中Step05到Step06的action配置,是否设置了错误的
popUpTo或launchSingleTop属性,导致Fragment实例重复创建或回栈异常。 - 生命周期日志追踪:在Step05Fragment的
onPause()、onResume()、handleNavigation()等关键方法中添加日志,输出当前状态和调用栈,明确循环触发的具体触发点,定位是导航重复执行还是生命周期被异常唤起。
内容的提问来源于stack exchange,提问作者RandomGuy
相关产品推荐
相关产品推荐

