002-实现多个Fragment切换方法封装及各子生命周期执行情况分析

2024-09-14 17:07 002-实现多个Fragment切换方法封装及各子生命周期执行情况分析已关闭评论

在Android开发中,FragmentTransaction 是用来管理 Fragment 的添加、移除、替换、显示和隐藏的主要工具。接下来我们会解释如何封装一个方法来实现多个 Fragment 的切换,并且分析每种操作(add, replace, show, hide)对 Fragment 生命周期的影响。

封装多个 Fragment 切换的方法

我们需要一个方法来切换两个 Fragment,我们可以创建一个辅助类或者方法来处理这些事务。将多个Fragment切换封装传入FragmentTransactionFragmenttag

public void switchFragment(FragmentTransaction fragmentTransaction, Fragment newFragment, String tag) {
    if (newFragment != null) {
        // 如果Fragment已经在FragmentManager中存在,则先从back stack中移除它
        if (newFragment.isAdded()) {
            fragmentTransaction.show(newFragment);
        } else {
            fragmentTransaction.add(R.id.fragment_container, newFragment, tag);
        }
    }
    fragmentTransaction.commit();
}

这个方法接受一个 FragmentTransaction 对象,一个新的 Fragment 和一个 tag。如果新的 Fragment 已经被添加到 FragmentManager 中,那么就显示它;否则,就将它添加到指定的容器中。

可以进一步封装,只需要传入对应的tag,同时允许传入参数Bundle

public void replaceFragment(String tag, Bundle bundle) {
    Fragment tempFragment = getSupportFragmentManager().findFragmentByTag(tag);
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    if (tempFragment == null) {
        try {
            //tempFragment = (Fragment) Class.forName(tag).newInstance();
            tempFragment = (Fragment) Class.forName(tag).getDeclaredConstructor().newInstance();//无参数的构造方法
            if (bundle!=null) {
                tempFragment.setArguments(bundle);
            }
            transaction.add(R.id.fragment, tempFragment, tag);
            this.curFragment = (BaseFragment) tempFragment;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    if (fragments != null) {
        for (int i = 0; i < fragments.size(); i++) {
            Fragment fragment = fragments.get(i);
            if (fragment.getTag().equals(tag)) {
                if (bundle!=null) {
                    fragment.setArguments(bundle);
                }
                transaction.show(fragment);
                this.curFragment = (BaseFragment) fragment;
            } else {
                transaction.hide(fragment);
            }
        }
    }
    transaction.commitAllowingStateLoss();

}

完善上述封装,增加调试信息,方便查阅

private void replaceFragment(String tag, Bundle bundle) {
    // 获取FragmentManager
    FragmentManager fragmentManager = getSupportFragmentManager();

    // 检查FragmentManager是否存在
    if (fragmentManager == null) {
        Log.e("TAG", "FragmentManager is null");
        return;
    }

    // 查找已存在的Fragment
    Fragment tempFragment = fragmentManager.findFragmentByTag(tag);

    // 开始事务
    FragmentTransaction transaction = fragmentManager.beginTransaction();

    // 如果Fragment不存在,创建一个新的Fragment
    if (tempFragment == null) {
        try {
            Class<?> clazz = Class.forName(tag);
            tempFragment = (Fragment) clazz.getDeclaredConstructor().newInstance();

            // 设置Bundle参数
            tempFragment.setArguments(bundle);

            // 添加Fragment到容器
            transaction.add(R.id.fragment, tempFragment, tag);
        } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
            Log.e("TAG", "Error creating fragment", e);
            return;
        }
    } else {
        // 如果Fragment存在,更新其参数
        tempFragment.setArguments(bundle);
    }

    // 遍历所有Fragment,只显示目标Fragment,隐藏其他Fragment
    List<Fragment> fragments = fragmentManager.getFragments();
    if (fragments != null) {
        for (Fragment fragment : fragments) {
            if (fragment != null && fragment.getTag().equals(tag)) {
                // 显示目标Fragment
                transaction.show(fragment);
                this.curFragment = (BaseFragment) fragment;
            } else if (fragment != null) {
                // 隐藏其他Fragment
                transaction.hide(fragment);
            }
        }
    }

    // 提交事务
    transaction.commitAllowingStateLoss();
}

Fragment 生命周期的影响

当使用 FragmentTransaction 的不同方法时,它们会影响 Fragment 的生命周期方法的调用。下面是每种方法对 Fragment 生命周期的影响:

  • add: 当添加一个新的 Fragment 到活动中时,它的生命周期会经历从 onAttach()onResume() 的所有阶段,前提是这个 Fragment 在添加后是可见的。

  • replace: replace 方法与 add 类似,但它会移除容器中现有的 Fragment 并添加新的 Fragment。对于新 Fragment,它的生命周期也是从 onAttach()onResume()。而对于被替换的 Fragment,它的生命周期将会经历从 onPause()onDetach()

  • show: 当展示一个已经添加但被隐藏的 Fragment 时,它的生命周期不会从头开始执行,只会从 onHiddenChanged(false) 开始,如果它之前是不可见的话。这意味着如果 Fragment 之前是暂停状态(paused),那么它将保持暂停状态直到活动恢复。

  • hide: 隐藏一个 Fragment 会触发 onHiddenChanged(true),但是其他生命周期方法如 onPause()onStop() 不会被调用。隐藏的 Fragment 仍然存在于活动中并且可能会接收一些事件。

commit、commitAllowingStateLoss和executePendingTransactions区别

  • 使用 commit() 方法提交 FragmentTransaction 时,需要确保不是在 onCreate(), onCreateView() 或者 onActivityCreated() 方法中进行,因为这可能导致内存泄漏或其他问题。
  • commit() 后,如果需要等待事务完成,可以使用 commitAllowingStateLoss() 或者通过 FragmentManagerexecutePendingTransactions() 方法。
  • 如果需要做更复杂的事务,例如回退堆栈的操作,可能需要使用 addToBackStack(String) 方法来管理事务的历史记录。
  • 应用需要支持API Level 17(Android 4.2)及以下版本,建议使用commit()而不是commitAllowingStateLoss(),因为后者允许在FragmentManager的状态丢失的情况下提交事务,这可能导致用户界面的意外行为。然而,对于现代Android应用,通常推荐使用commitAllowingStateLoss(),因为它提供了更好的用户体验。

当前文章价值0.36元,扫一扫支付后添加微信提供帮助!(如不能解决您的问题,可以申请退款)

你可能感兴趣的文章

来源:每日教程每日一例,深入学习实用技术教程,关注公众号TeachCourse
转载请注明出处: https://teachcourse.cn/3675.html ,谢谢支持!

资源分享

Python库flask实现激活码功能具体实现 Python库flask实现激活码功能具
隐式意图获取所有符合的Activity 隐式意图获取所有符合的Activit
结合实例讲解Glide图片变换(Transformation)的常见场景应用 结合实例讲解Glide图片变换(T
Python开发后端API详细介绍 Python开发后端API详细介绍

评论已关闭!