You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android返回键需多次点击关闭App,Fragment重复重建问题求助

Android应用Fragment重复重建与返回键异常问题

我的Android应用包含带7个Fragment的导航抽屉,在应用启动时,或是从详情Activity返回后,点击返回键会出现Fragment重复重建的情况,并且需要多次点击返回键才能关闭应用。

MainActivity代码

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    var APP_START_TIME: Long = 0


    private lateinit var appBarConfiguration: AppBarConfiguration
    private var _binding: ActivityMainBinding? = null
    private val binding get() = _binding!!
    private lateinit var navController: NavController
    private lateinit var postViewModel: PostViewModel
    private var _navGraph: NavGraph? = null
    private val navGraph get() = _navGraph!!
    lateinit var adView: AdView
    private var adRequest: AdRequest? = null


    private val applicationScope = CoroutineScope(Dispatchers.Unconfined)


    override fun onDestroy() {
        super.onDestroy()

        adView.destroy()
        adRequest = null
        _binding = null
    }

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)
        APP_START_TIME = System.currentTimeMillis()
        _binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)


        adView = AdView(this)
        delayedInit()
        postViewModel = ViewModelProvider(this)[PostViewModel::
        class.java]


        setSupportActionBar(binding.toolbar)


        val drawerLayout: DrawerLayout = binding.drawerLayout


        val navHostFragment =
            supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment?

        if (navHostFragment != null) {
            navController = navHostFragment.navController
        }




        appBarConfiguration = AppBarConfiguration(
            setOf(
                R.id.nav_home, R.id.nav_accessory,
                R.id.nav_arcade, R.id.nav_fashion,
                R.id.nav_food, R.id.nav_heath,
                R.id.nav_lifestyle, R.id.nav_sports, R.id.nav_favorites, R.id.settingsFragment
            ), drawerLayout
        )



        setupActionBarWithNavController(this, navController, appBarConfiguration)
        setupWithNavController(binding.navView, navController)

        _navGraph = navController.navInflater.inflate(R.navigation.mobile_navigation)


        onBackPressedDispatcher.addCallback(this /* lifecycle owner */,
            object : OnBackPressedCallback(true) {
                override fun handleOnBackPressed() {
                    // Back is pressed... Finishing the activity

                    finish()
                }
            })
}

//    override fun onStart() {
//        super.onStart()
//    }


    override fun onPause() {
        super.onPause()
        adView.pause()
    }

    override fun onResume() {
        super.onResume()
        adView.resume()

        postViewModel.currentDestination.observe(this) { currentDestination ->

            Log.w(TAG, "currentDestination: at first run is $currentDestination")

            navGraph.setStartDestination(currentDestination)
            navController.graph = navGraph


        }

        navController.addOnDestinationChangedListener { _, destination, _ ->
            Log.d(TAG, "addOnDestinationChangedListener: " + destination.id)

            if (destination.id != R.id.settingsFragment
                && destination.id != R.id.aboutFragment
                && destination.id != R.id.privacyPolicyFragment
            ) {
                postViewModel.saveCurrentDestination(destination.id)
            }

        }
    }

    private fun requestHomeBanner() {

        adRequest = Constants.callAndBuildAdRequest()
        adView.adListener = object : AdListener() {

            override fun onAdFailedToLoad(adError: LoadAdError) {
                Log.e(TAG, "onAdFailedToLoad: ${adError.cause.toString()}")
                Log.e(TAG, "onAdFailedToLoad: ${adError.responseInfo.toString()}")
            }

        }



        adRequest?.let { adView.loadAd(it) }


    }



    private fun delayedInit() = applicationScope.launch {
        binding.adViewContainer.addView(adView)
        adView.adUnitId = "ca-app-pub-3940256099942544/6300978111"
        adView.setAdSize(Constants.GET_AD_SIZE(this@MainActivity))


        val testDeviceIds = listOf("048DC5C3C06FBD17D9AD205151167F48")
        val configuration = RequestConfiguration.Builder().setTestDeviceIds(testDeviceIds).build()
        MobileAds.setRequestConfiguration(configuration)


        if (Utils.hasInternetConnection(this@MainActivity)) {
            requestTheLatestConsentInformation(this@MainActivity)
            MobileAds.initialize(this@MainActivity) {
                Log.d(TAG, "onInitCompleted")
            }

            requestHomeBanner()
        }
    }


    override fun onSupportNavigateUp(): Boolean {
        return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
    }

}

尝试过的无效解决方法

  • 在OnBackPressedCallback中添加代码:
navGraph.clear()
binding.drawerLayout.removeAllViews()
binding.navView.removeAllViews()
  • 在addOnDestinationChangedListener中添加onBackPressedDispatcher回调:
onBackPressedDispatcher.addCallback(this /* lifecycle owner */,
    object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            // Back is pressed... Finishing the activity

            navController.clearBackStack(destination.id)
            finish()
        }
    })
  • 在Fragment中处理返回键事件:
requireActivity()
    .onBackPressedDispatcher
    .addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            Log.d(TAG, "Fragment back pressed invoked")

//                    hideShimmerEffect()
            // Do custom work here



            requireActivity().finish()

      //       if you want onBackPressed() to be called as normal afterwards
            if (isEnabled) {
                isEnabled = false
                requireActivity().onBackPressed()
            }
        }
    })
  • 添加出栈或清空回退栈的代码:
findNavController().popBackStack()
findNavController().clearBackStack(R.id.nav_home)
  • 修改onSupportNavigateUp方法:
override fun onSupportNavigateUp(): Boolean {
    return if(supportFragmentManager.backStackEntryCount > 0){
        navController.navigateUp(appBarConfiguration)
    }else {
        finish()
        super.onSupportNavigateUp()

    }
}

内容的提问来源于Stack Exchange,提问作者Dr Mido

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 06:40:28