Fragment Management

本文深入探讨FragmentManager在Android中的应用,包括如何管理Activity中的fragments、获取存在的fragment、使用popBackStack实现片段回退以及执行FragmentTransactions进行片段的增加、移除、替换等操作。通过实例代码展示了如何创建、管理、回退片段以及事务动画的应用。
  • FragmentManager

  使用FragmentManager管理Activity中的fragments,调用Activity中的getFragmentManager()方法。

  因为FragmentManager的API是在Android 3.0,也即API level 11开始引入的,所以兼容之前的版本,需要使用support library中的FragmentActivity,并且使用getSupportFragmentManager()方法。

 

 得到Activity中存在的fragment:使用findFragmentById()或findFragmentByTag()方法。

 

popBackStack():将back stack中最后一次的fragment转换弹出。如果没有可以出栈的东西,返回false。

这个函数是异步的:它将弹出栈的请求加入队列,但是这个动作直到应用回到事件循环才会执行。

 

为back stack加上监听器:addOnBackStackChangedListener()

 

  • Performing Fragment Transactions

  使用Fragment时,可以通过用户交互来执行一些动作,比如增加、移除、替换等。所有这些改变构成一个集合,这个集合被叫做一个transaction。

  可以调用FragmentTransaction中的方法来处理这个transaction,并且可以将transaction存进由activity管理的back stack中,这样用户就可以进行fragment变化的回退操作。

  可以这样得到FragmentTransaction类的实例: 

 

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

  每个transaction是一组同时执行的变化的集合。

  用add(), remove(), replace()方法,把所有需要的变化加进去,然后调用commit()方法,将这些变化应用。

  在commit()方法之前,你可以调用addToBackStack(),把这个transaction加入back stack中去,这个back stack是由activity管理的,当用户按返回键时,就会回到上一个fragment的状态。

  比如下面的代码就是用一个新的fragment取代之前的fragment,并且将前次的状态存储在back stack中。

 

// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
 
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
 
// Commit the transaction
transaction.commit();

  在这个例子中,newFragment将取代在R.id.fragment_container容器中的fragment,如果没有,将直接添加新的fragment。

  通过调用addToBackStack(),commit()的一系列转换作为一个transaction被存储在back stack中,用户按Back键可以返回上一个转换前的状态。

  当你移除一个fragment的时候,如果commit()之前没有调用addToBackStack(),那个fragment将会是destroyed;如果调用了addToBackStack(),这个fragment会是stopped,可以通过返回键来恢复。

      如果添加多个变化到事务(例如add()或remove())并调用addToBackStack(), 然后在你调用commit()之前的所有应用的变化会被作为一个单个事务添加到后台堆栈, BACK按键会将它们一起回退.

 

关于commit()方法

  调用commit()方法并不能立即执行transaction中包含的改变动作,commit()方法把transaction加入activity的UI线程队列中。

  但是,如果觉得有必要的话,可以调用executePendingTransactions()方法来立即执行commit()提供的transaction。

  这样做通常是没有必要的,除非这个transaction被其他线程依赖。

  注意:你只能在activity存储它的状态(当用户要离开activity时)之前调用commit(),如果在存储状态之后调用commit(),将会抛出一个异常。

这是因为当activity再次被恢复时commit之后的状态将丢失。如果丢失也没关系,那么使用commitAllowingStateLoss()方法。

 

 

添加变化到 FragmentTransaction的顺序不重要, 除以下例外:
  • 必须最后调用 commit().
  • 如果添加多个fragment到同一个容器, 那么添加的顺序决定了它们在view hierarchy中显示的顺序.
当执行一个移除fragment的事务时, 如果没有调用 addToBackStack(), 那么当事务提交后, 那个fragment会被销毁,并且用户不能导航回到它. 有鉴于此, 当移除一个fragment时,如果调用了 addToBackStack(), 那么fragment会被停止, 如果用户导航回来,它将会被恢复.
提示: 对于每一个fragment事务, 你可以应用一个事务动画, 通过在提交事务之前调用setTransition()实现.
调用 commit() 并不立即执行事务.恰恰相反, 它将事务安排排期, 一旦准备好, 就在activity的UI线程上运行(主线程).如果有必要, 无论如何, 你可以从你的UI线程调用 executePendingTransactions() 来立即执行由commit()提交的事务. 但这么做通常不必要, 除非事务是其他线程中的job的一个从属.
这是完整代码,解释为什么首次添加的fragment也有tagpackage com.tplink.omada.sdncontroller.ui.settings.networksecurity.appcontrol import android.app.Activity import android.content.Intent import android.view.View import androidx.fragment.app.Fragment import com.tplink.omada.R import com.tplink.omada.common.utils.StartActivityForResultLauncher import com.tplink.omada.databinding.SdnActivityAppControlBinding import com.tplink.omada.libnetwork.sdncontroller.model.appcontrol.AppFilterItem import com.tplink.omada.libnetwork.sdncontroller.model.appcontrol.AppRuleItem import com.tplink.omada.libnetwork.sdncontroller.model.appcontrol.AssignRestrictionItem import com.tplink.omada.libutility.log.Log import com.tplink.omada.sdncontroller.SdnBaseActivity import com.tplink.omada.sdncontroller.ui.settings.wireless.SdnWlanScheduleActivity import com.tplink.omada.sdncontroller.viewmodel.settings.networksecurity.AppControlViewModel /** * Application Control 功能页 * * Created by libaoluo */ class SdnAppControlActivity : SdnBaseActivity<SdnActivityAppControlBinding, AppControlViewModel>(), AppControlNavigationCallback { companion object { const val APP_CONTROL_ENTER_STEP = "app_control_enter_step" @JvmStatic fun launchActivity(activity: Activity, step: AppControlStep) { val i = Intent(activity, SdnAppControlActivity::class.java) .putExtra(APP_CONTROL_ENTER_STEP, step) activity.startActivity(i) } } private var fragmentMap = HashMap<AppControlStep, Fragment>() private lateinit var currentFragment: Fragment private lateinit var currentStep: AppControlStep private val mActivityResultLauncher = StartActivityForResultLauncher(this) override fun getLayoutId(): Int = R.layout.sdn_activity_app_control override fun getViewModel(): Class<AppControlViewModel> = AppControlViewModel::class.java override fun initView() { initFragments() } override fun initData() {} override fun setOnClick(v: View) {} override fun onBack(step: AppControlStep) { when (step) { AppControlStep.DPI, AppControlStep.APPLICATION_FILTER -> finish() AppControlStep.RULES_MANAGEMENT -> viewModel.rulesManagementPrevStep?.let { backToFragment( it ) } ?: finish() AppControlStep.ASSIGN_RESTRICTION_EDIT -> backToFragment(AppControlStep.DPI) AppControlStep.APPLICATION_FILTER_EDIT -> backToFragment(AppControlStep.APPLICATION_FILTER) AppControlStep.RULES_SELECTION -> backToFragment(AppControlStep.APPLICATION_FILTER_EDIT) AppControlStep.RULES_MANAGEMENT_EDIT -> backToFragment(viewModel.editRulePrevStep) AppControlStep.APP_SELECTION -> backToFragment(AppControlStep.RULES_MANAGEMENT_EDIT) else -> {} } } override fun onDpiOpen() { onFragmentOpen(AppControlStep.DPI) } override fun onAssignRestrictionEditOpen( isAddMode: Boolean, restrictionItem: AssignRestrictionItem ) { viewModel.apply { isAddRestrictionMode = isAddMode oldRestrictionItem = restrictionItem newRestrictionItem = restrictionItem.copy() } // 打开新页面 onFragmentOpen(AppControlStep.ASSIGN_RESTRICTION_EDIT) } override fun onAppFilterOpen() { onFragmentOpen(AppControlStep.APPLICATION_FILTER) } override fun onAppFilterEditOpen(isAddMode: Boolean, filterItem: AppFilterItem) { viewModel.apply { isAddFilterMode = isAddMode oldFilterItem = filterItem newFilterItem = filterItem.copy() } onFragmentOpen(AppControlStep.APPLICATION_FILTER_EDIT) } override fun onRulesSelectionOpen() { onFragmentOpen(AppControlStep.RULES_SELECTION) } override fun onRulesManagementOpen(prevStep: AppControlStep?) { viewModel.rulesManagementPrevStep = prevStep onFragmentOpen(AppControlStep.RULES_MANAGEMENT) } override fun onRulesManagementEditOpen( isAddMode: Boolean, ruleItem: AppRuleItem, prevStep: AppControlStep ) { viewModel.apply { isAddRuleMode = isAddMode editRulePrevStep = prevStep oldRuleItem = ruleItem newRuleItem = ruleItem.copy() } onFragmentOpen(AppControlStep.RULES_MANAGEMENT_EDIT) } override fun onTimeRangeOpen() { val i = SdnWlanScheduleActivity.newIntent( context = this, isScheduleOn = true, action = 0, scheduleId = viewModel.newRuleItem?.schedule ?: "", fromPage = SdnWlanScheduleActivity.FROM_PAGE_APP_CONTROL ) mActivityResultLauncher.launch(i) { activityResult -> activityResult.takeIf { it.resultCode == RESULT_OK && it.data != null } ?.let { val schedule = it.data?.getStringExtra(SdnWlanScheduleActivity.SELECTED_SCHEDULE_ID_RESULT) viewModel.newRuleItem?.schedule = schedule } } } override fun onAppSelectionOpen() { onFragmentOpen(AppControlStep.APP_SELECTION) } private fun initFragments() { fragmentMap.apply { put(AppControlStep.DPI, SdnAppControlDpiFragment.newInstance()) put(AppControlStep.ASSIGN_RESTRICTION_EDIT, SdnEditAppRestrictionFragment.newInstance()) put(AppControlStep.APPLICATION_FILTER, SdnAppFilterFragment.newInstance()) put(AppControlStep.APPLICATION_FILTER_EDIT, SdnEditAppFilterFragment.newInstance()) put(AppControlStep.RULES_SELECTION, SdnSelectRulesFragment.newInstance()) put(AppControlStep.RULES_MANAGEMENT, SdnRulesManagementFragment.newInstance()) put(AppControlStep.RULES_MANAGEMENT_EDIT, SdnEditAppRuleFragment.newInstance()) put(AppControlStep.APP_SELECTION, SdnSelectAppsFragment.newInstance()) } val fragmentManager = supportFragmentManager val fragments = fragmentManager.fragments val transaction = fragmentManager.beginTransaction() if (!isRestore) { // ✅ 首次进入:创建并显示初始 Fragment getNewInstanceFragment(AppControlStep.DPI)?.let { newFragment -> fragmentMap[AppControlStep.DPI] = newFragment currentStep = AppControlStep.DPI currentFragment = newFragment transaction.add(R.id.content_frame, newFragment) transaction.commitAllowingStateLoss() } } else { printFragmentListWithVisibility() // ✅ 重建:从 FragmentManager 恢复AQ if (fragments.isNotEmpty()) { // 🧭 关键改进:找出当前“显示”的 Fragment(即 isVisible == true) val visibleFragment = fragments.firstOrNull { it.isVisible } if (visibleFragment != null) { val restoredStep = AppControlStep.values().firstOrNull { step -> getNewInstanceFragment(step)?.javaClass == visibleFragment.javaClass } ?: AppControlStep.DPI currentStep = restoredStep currentFragment = visibleFragment fragmentMap[restoredStep] = visibleFragment // 🚨 修复重叠问题:仅显示当前 visible 的 fragment,隐藏其他所有 fragments.forEach { frag -> if (frag != visibleFragment) transaction.hide(frag) } transaction.show(visibleFragment) transaction.commitAllowingStateLoss() } else { // 🧩 如果没有任何 Fragment 是可见的(极少数情况) val fallback = fragments.lastOrNull() ?: getNewInstanceFragment(AppControlStep.DPI) if (fallback != null) { val restoredStep = AppControlStep.values().firstOrNull { step -> getNewInstanceFragment(step)?.javaClass == fallback.javaClass } ?: AppControlStep.DPI currentStep = restoredStep currentFragment = fallback fragmentMap[restoredStep] = fallback transaction.show(fallback) transaction.commitAllowingStateLoss() } } } else { // 🚨 FragmentManager 没有恢复任何 Fragment(例如进程被杀后彻底重建) getNewInstanceFragment(AppControlStep.DPI)?.let { fallback -> fragmentMap[AppControlStep.DPI] = fallback currentStep = AppControlStep.DPI currentFragment = fallback transaction.add(R.id.content_frame, fallback) transaction.commitAllowingStateLoss() } } } } private fun printFragmentListWithVisibility() { val fragmentManager = supportFragmentManager val fragments = fragmentManager.fragments Log.d( "重建测试", "last Fragment: ${fragments.last()}, 可见性: ${if (fragments.last().isVisible) "可见" else "不可见"}" ) fragments.forEach { fragment -> val isVisible = fragment.isVisible val fragmentTag = fragment.javaClass.simpleName Log.d( "重建测试", "Fragment Tag: $fragmentTag,Fragment: $fragment, 可见性: ${if (isVisible) "可见" else "不可见"}" ) } } private fun addFragment(fragment: Fragment, tag: String) { supportFragmentManager.beginTransaction() .add(R.id.content_frame, fragment, tag) .commitAllowingStateLoss() Log.d("重建测试", "addFragment:$fragment") } private fun onFragmentOpen(step: AppControlStep) { val fragment = if (fragmentMap.containsKey(step) && fragmentMap[step] != null) { fragmentMap[step] } else { getNewInstanceFragment(step)?.let { fragmentMap[step] = it } fragmentMap[step] } fragment?.let { switchFragment(it, step) } } private fun backToFragment(step: AppControlStep) { Log.d("重建测试", "backToFragmentfragmentMap[step]值:${fragmentMap[step]}") fragmentMap[step]?.let { switchFragment(it, step) } } private fun switchFragment(targetFragment: Fragment, tag: AppControlStep) { val transaction = supportFragmentManager.beginTransaction() if (!targetFragment.isAdded) { transaction.hide(currentFragment) transaction.add(R.id.content_frame, targetFragment, targetFragment.javaClass.name) Log.d( "重建测试", "switchFragment未添加:$targetFragment,currentFragment:${currentFragment},targetFragment:$targetFragment" ) } else { currentFragment.let { transaction.hide(it).show(targetFragment) } Log.d( "重建测试", "switchFragment已添加添加:$targetFragment,currentFragment:${currentFragment},targetFragment:$targetFragment" ) } currentFragment = targetFragment currentStep = tag transaction.commitAllowingStateLoss() } private fun getNewInstanceFragment(step: AppControlStep): Fragment? { return when (step) { AppControlStep.DPI -> SdnAppControlDpiFragment.newInstance() AppControlStep.ASSIGN_RESTRICTION_EDIT -> SdnEditAppRestrictionFragment.newInstance() AppControlStep.APPLICATION_FILTER -> SdnAppFilterFragment.newInstance() AppControlStep.APPLICATION_FILTER_EDIT -> SdnEditAppFilterFragment.newInstance() AppControlStep.RULES_SELECTION -> SdnSelectRulesFragment.newInstance() AppControlStep.RULES_MANAGEMENT -> SdnRulesManagementFragment.newInstance() AppControlStep.RULES_MANAGEMENT_EDIT -> SdnEditAppRuleFragment.newInstance() AppControlStep.APP_SELECTION -> SdnSelectAppsFragment.newInstance() else -> null } } }
10-15
private fun initFragments() { fragmentMap.apply { put(AppControlStep.DPI, SdnAppControlDpiFragment.newInstance()) put(AppControlStep.ASSIGN_RESTRICTION_EDIT, SdnEditAppRestrictionFragment.newInstance()) put(AppControlStep.APPLICATION_FILTER, SdnAppFilterFragment.newInstance()) put(AppControlStep.APPLICATION_FILTER_EDIT, SdnEditAppFilterFragment.newInstance()) put(AppControlStep.RULES_SELECTION, SdnSelectRulesFragment.newInstance()) put(AppControlStep.RULES_MANAGEMENT, SdnRulesManagementFragment.newInstance()) put(AppControlStep.RULES_MANAGEMENT_EDIT, SdnEditAppRuleFragment.newInstance()) put(AppControlStep.APP_SELECTION, SdnSelectAppsFragment.newInstance()) } val fragmentManager = supportFragmentManager val fragments = fragmentManager.fragments val transaction = fragmentManager.beginTransaction() if (!isRestore) { // ✅ 首次进入:创建并显示初始 Fragment getNewInstanceFragment(AppControlStep.DPI)?.let { newFragment -> fragmentMap[AppControlStep.DPI] = newFragment currentStep = AppControlStep.DPI currentFragment = newFragment transaction.add(R.id.content_frame, newFragment) transaction.commitAllowingStateLoss() } } else { // ✅ 重建:从 FragmentManager 恢复 if (fragments.isNotEmpty()) { // 🧭 关键改进:找出当前“显示”的 Fragment(即 isVisible == true) val visibleFragment = fragments.firstOrNull { it.isVisible } if (visibleFragment != null) { val restoredStep = AppControlStep.values().firstOrNull { step -> getNewInstanceFragment(step)?.javaClass == visibleFragment.javaClass } ?: AppControlStep.DPI currentStep = restoredStep currentFragment = visibleFragment fragmentMap[restoredStep] = visibleFragment // 🚨 修复重叠问题:仅显示当前 visible 的 fragment,隐藏其他所有 fragments.forEach { frag -> if (frag != visibleFragment) transaction.hide(frag) } transaction.show(visibleFragment) transaction.commitAllowingStateLoss() } else { // 🧩 如果没有任何 Fragment 是可见的(极少数情况) val fallback = fragments.lastOrNull() ?: getNewInstanceFragment(AppControlStep.DPI) if (fallback != null) { val restoredStep = AppControlStep.values().firstOrNull { step -> getNewInstanceFragment(step)?.javaClass == fallback.javaClass } ?: AppControlStep.DPI currentStep = restoredStep currentFragment = fallback fragmentMap[restoredStep] = fallback transaction.show(fallback) transaction.commitAllowingStateLoss() } } } else { // 🚨 FragmentManager 没有恢复任何 Fragment(例如进程被杀后彻底重建) getNewInstanceFragment(AppControlStep.DPI)?.let { fallback -> fragmentMap[AppControlStep.DPI] = fallback currentStep = AppControlStep.DPI currentFragment = fallback transaction.add(R.id.content_frame, fallback) transaction.commitAllowingStateLoss() } } } }自顶向下打印fragmentmanager中fragment列表与对应可见性
10-15
那么在下面的代码中,什么情况会出现上面说的报错:package com.tplink.omada.sdncontroller.ui.settings.networksecurity.appcontrol import android.app.Activity import android.content.Intent import android.view.View import androidx.fragment.app.Fragment import com.tplink.omada.R import com.tplink.omada.common.utils.StartActivityForResultLauncher import com.tplink.omada.common.utils.getSerializableExtraCompat import com.tplink.omada.databinding.SdnActivityAppControlBinding import com.tplink.omada.libnetwork.sdncontroller.model.appcontrol.AppFilterItem import com.tplink.omada.libnetwork.sdncontroller.model.appcontrol.AppRuleItem import com.tplink.omada.libnetwork.sdncontroller.model.appcontrol.AssignRestrictionItem import com.tplink.omada.libutility.log.Log import com.tplink.omada.sdncontroller.SdnBaseActivity import com.tplink.omada.sdncontroller.ui.settings.wireless.SdnWlanScheduleActivity import com.tplink.omada.sdncontroller.viewmodel.settings.networksecurity.AppControlViewModel /** * Application Control 功能页 * * Created by libaoluo */ class SdnAppControlActivity : SdnBaseActivity<SdnActivityAppControlBinding, AppControlViewModel>(), AppControlNavigationCallback { companion object { const val APP_CONTROL_ENTER_STEP = "app_control_enter_step" @JvmStatic fun launchActivity(activity: Activity, step: AppControlStep) { val i = Intent(activity, SdnAppControlActivity::class.java) .putExtra(APP_CONTROL_ENTER_STEP, step) activity.startActivity(i) } } private var fragmentMap = HashMap<AppControlStep, Fragment>() private lateinit var currentFragment: Fragment private lateinit var currentStep: AppControlStep private val mActivityResultLauncher = StartActivityForResultLauncher(this) override fun getLayoutId(): Int = R.layout.sdn_activity_app_control override fun getViewModel(): Class<AppControlViewModel> = AppControlViewModel::class.java override fun initView() { initFragments() } override fun initData() {} override fun setOnClick(v: View) {} override fun onBack(step: AppControlStep) { when (step) { AppControlStep.DPI, AppControlStep.APPLICATION_FILTER -> finish() AppControlStep.RULES_MANAGEMENT -> viewModel.rulesManagementPrevStep?.let { backToFragment( it ) } ?: finish() AppControlStep.ASSIGN_RESTRICTION_EDIT -> backToFragment(AppControlStep.DPI) AppControlStep.APPLICATION_FILTER_EDIT -> backToFragment(AppControlStep.APPLICATION_FILTER) AppControlStep.RULES_SELECTION -> backToFragment(AppControlStep.APPLICATION_FILTER_EDIT) AppControlStep.RULES_MANAGEMENT_EDIT -> backToFragment(viewModel.editRulePrevStep) AppControlStep.APP_SELECTION -> backToFragment(AppControlStep.RULES_MANAGEMENT_EDIT) else -> {} } } override fun onDpiOpen() { onFragmentOpen(AppControlStep.DPI) } override fun onAssignRestrictionEditOpen( isAddMode: Boolean, restrictionItem: AssignRestrictionItem ) { viewModel.apply { isAddRestrictionMode = isAddMode oldRestrictionItem = restrictionItem newRestrictionItem = restrictionItem.copy() } // 打开新页面 onFragmentOpen(AppControlStep.ASSIGN_RESTRICTION_EDIT) } override fun onAppFilterOpen() { onFragmentOpen(AppControlStep.APPLICATION_FILTER) } override fun onAppFilterEditOpen(isAddMode: Boolean, filterItem: AppFilterItem) { viewModel.apply { isAddFilterMode = isAddMode oldFilterItem = filterItem newFilterItem = filterItem.copy() } onFragmentOpen(AppControlStep.APPLICATION_FILTER_EDIT) } override fun onRulesSelectionOpen() { onFragmentOpen(AppControlStep.RULES_SELECTION) } override fun onRulesManagementOpen(prevStep: AppControlStep?) { viewModel.rulesManagementPrevStep = prevStep onFragmentOpen(AppControlStep.RULES_MANAGEMENT) } override fun onRulesManagementEditOpen( isAddMode: Boolean, ruleItem: AppRuleItem, prevStep: AppControlStep ) { viewModel.apply { isAddRuleMode = isAddMode editRulePrevStep = prevStep oldRuleItem = ruleItem newRuleItem = ruleItem.copy() } onFragmentOpen(AppControlStep.RULES_MANAGEMENT_EDIT) } override fun onTimeRangeOpen() { val i = SdnWlanScheduleActivity.newIntent( context = this, isScheduleOn = true, action = 0, scheduleId = viewModel.newRuleItem?.schedule ?: "", fromPage = SdnWlanScheduleActivity.FROM_PAGE_APP_CONTROL ) mActivityResultLauncher.launch(i) { activityResult -> activityResult.takeIf { it.resultCode == RESULT_OK && it.data != null } ?.let { val schedule = it.data?.getStringExtra(SdnWlanScheduleActivity.SELECTED_SCHEDULE_ID_RESULT) viewModel.newRuleItem?.schedule = schedule } } } override fun onAppSelectionOpen() { onFragmentOpen(AppControlStep.APP_SELECTION) } private fun initFragments() { val fragmentManager = supportFragmentManager val transaction = fragmentManager.beginTransaction() // 1. 初始化 fragmentMap:先尝试从 FragmentManager 获取已存在的 Fragment,没有就创建 AppControlStep.values().forEach { step -> val fragment = fragmentManager.findFragmentByTag(step.name) ?: getNewInstanceFragment(step) fragment?.let { fragmentMap[step] = it } } // 2. 获取当前 Step:优先从 ViewModel,首次启动用 intent 或默认 DPI currentStep = viewModel.currentStep ?: intent.getSerializableExtraCompat(APP_CONTROL_ENTER_STEP, AppControlStep::class.java) ?: AppControlStep.DPI // 3. 获取 currentFragment,兜底防空 currentFragment = fragmentMap[currentStep] ?: fragmentMap.values.first() // 4. 将所有 Fragment 添加到容器,并统一显示/隐藏 fragmentMap.forEach { (step, fragment) -> if (fragment.isAdded) { if (step == currentStep) transaction.show(fragment) else transaction.hide(fragment) } else { transaction.add(R.id.content_frame, fragment, step.name) if (step != currentStep) transaction.hide(fragment) } } transaction.commitAllowingStateLoss() } private fun printFragmentListWithVisibility() { val fragmentManager = supportFragmentManager val fragments = fragmentManager.fragments if (fragments.isEmpty()) { Log.d("重建测试", "FragmentManager 当前没有任何 Fragment") return } // 打印最后一个 Fragment(安全版) fragments.lastOrNull()?.let { lastFragment -> Log.d( "重建测试", "last Fragment: $lastFragment, 可见性: ${if (lastFragment.isVisible) "可见" else "不可见"}" ) } // 遍历打印所有 Fragment fragments.forEach { fragment -> val isVisible = fragment.isVisible val fragmentTag = fragment.tag ?: fragment.javaClass.simpleName Log.d( "重建测试", "Fragment Tag: $fragmentTag, Fragment: $fragment, 可见性: ${if (isVisible) "可见" else "不可见"}" ) } } private fun addFragment(fragment: Fragment, tag: String) { supportFragmentManager.beginTransaction() .add(R.id.content_frame, fragment, tag) .commitAllowingStateLoss() Log.d("重建测试", "addFragment:$fragment") } private fun onFragmentOpen(step: AppControlStep) { val fragment = if (fragmentMap.containsKey(step) && fragmentMap[step] != null) { fragmentMap[step] } else { getNewInstanceFragment(step)?.let { fragmentMap[step] = it } fragmentMap[step] } fragment?.let { switchFragment(it, step) } } private fun backToFragment(step: AppControlStep) { Log.d("重建测试", "backToFragmentfragmentMap[step]值:${fragmentMap[step]}") fragmentMap[step]?.let { switchFragment(it, step) } } private fun switchFragment(targetFragment: Fragment, tag: AppControlStep) { if (targetFragment == currentFragment) return // 防止重复显示 val transaction = supportFragmentManager.beginTransaction() if (!targetFragment.isAdded) { transaction.hide(currentFragment) transaction.add(R.id.content_frame, targetFragment, targetFragment.javaClass.name) Log.d( "重建测试", "switchFragment未添加:$targetFragment,currentFragment:${currentFragment},targetFragment:$targetFragment" ) } else { currentFragment.let { transaction.hide(it).show(targetFragment) } Log.d( "重建测试", "switchFragment已添加添加:$targetFragment,currentFragment:${currentFragment},targetFragment:$targetFragment" ) } currentFragment = targetFragment currentStep = tag viewModel.currentStep = tag transaction.commitAllowingStateLoss() } private fun getNewInstanceFragment(step: AppControlStep): Fragment? { return when (step) { AppControlStep.DPI -> SdnAppControlDpiFragment.newInstance() AppControlStep.ASSIGN_RESTRICTION_EDIT -> SdnEditAppRestrictionFragment.newInstance() AppControlStep.APPLICATION_FILTER -> SdnAppFilterFragment.newInstance() AppControlStep.APPLICATION_FILTER_EDIT -> SdnEditAppFilterFragment.newInstance() AppControlStep.RULES_SELECTION -> SdnSelectRulesFragment.newInstance() AppControlStep.RULES_MANAGEMENT -> SdnRulesManagementFragment.newInstance() AppControlStep.RULES_MANAGEMENT_EDIT -> SdnEditAppRuleFragment.newInstance() AppControlStep.APP_SELECTION -> SdnSelectAppsFragment.newInstance() else -> null } } override fun onResume() { super.onResume() printFragmentListWithVisibility() } }
最新发布
10-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值