【问题标题】:Proper way to remove a child fragment from a FrameLayout with multiple sources从具有多个源的 FrameLayout 中删除子片段的正确方法
【发布时间】:2021-09-10 23:22:30
【问题描述】:

我有一个 FrameLayout,它可以根据用户在 RadioGroup 上的选择填充不同的片段。但是,我很确定我用来去除此类碎片的方法远非理想,如果可能的话,我想了解如何正确地做到这一点。

我现在如何移除碎片:

(...)
//Inside the body of the OnViewCreated
FragmentManager manager = getChildFragmentManager();

//RadioGroup listener to show a fragment based on the user's choice
radioGroup.setOnCheckedChangeListener((group, checkedId) -> {
            //getCheckedRadio is only a method I created to get the index of the option chosen by the user
            int index = getCheckedRadio(group);
            switch (index) {
                case 1:
                    getChildFragmentManager().beginTransaction().replace(R.id.child_fragment, new FragmentA()).commit();
                    break;
                case 2:
                    getChildFragmentManager().beginTransaction().replace(R.id.child_fragment, new FragmentB()).commit();
                    break;
                case 3:
                    getChildFragmentManager().beginTransaction().replace(R.id.child_fragment, new FragmentC()).commit();
                    break;
                default:
                    removeFragments();
                    break;
            }
(...)

//Method I use to remove the fragments
public void removeFragments() {
        try {
            FragmentA fragA = (FragmentA) manager.findFragmentById(R.id.child_fragment);
            if (fragA != null)
                manager.beginTransaction().remove(fragA).commit();
        } catch (Exception e) {
            try {
                FragmentB fragB = (FragmentB) manager.findFragmentById(R.id.child_fragment);
                if (fragB != null)
                manager.beginTransaction().remove(fragB).commit();
            } catch (Exception f) {
                try {
                    FragmentC fragC = (FragmentC) manager.findFragmentById(R.id.child_fragment);
                    if (fragC != null)
                        manager.beginTransaction().remove(fragC).commit();
                } catch (Exception g) {
                    Toast.makeText(getContext(), "Try Again", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }

但是,我知道这种方法远非完美,因为如果我在 radioGroup.SetOnCheckedChangeListener 之外的任何时候调用它,它不会删除当时暴露的片段。所以我的问题是:从可以容纳不同类型片段的 FrameLayout 中删除片段的正确方法是什么?以及为什么我的 removeFragments() 方法在此侦听器上使用时有效,但在代码中的其他点调用时无效?

【问题讨论】:

    标签: java android android-fragments


    【解决方案1】:

    从可以容纳不同类型 Fragment 的 FrameLayout 中删除 Fragment 的正确方法是什么?

    第一

    无需为FrameLayout 占位符可以托管哪些类型的片段而烦恼;归根结底,它们都是片段(即Fragment 类的子类)。

    第二

    不知道是不是对分片交易概念有误解;正如 removeFragments() 方法的名称所暗示的那样,一次从单个占位符中删除多个片段;并且该方法的逻辑将其应用于FragmentA, B, & C(即认为一次可以存在多个片段);这是不对的;一次,一个占位符/容器只能容纳一个片段。

    这与根据用户导航可以有多个片段实例的返回堆栈不同。

    所以,removeFragments() 实际上需要是 removeFragment(),其中一次只需要删除一个片段。

    我猜你认为替换片段会将旧片段保留在占位符中,as per documentation

    调用replace()相当于在容器中调用remove(),并在同一个容器中添加一个新的片段。

    第三

    无需将remove(fragment) 包装到try catch 块中;这个方法根本没有通过任何异常,所以你永远不会进入catch块;即使该片段不是容器的当前片段,它也会默默地丢弃它。

    所以,removeFragments() 中的逻辑可以简化为:

    public void removeFragment() {
        Fragment fragment = manager.findFragmentById(R.id.child_fragment);
        if (fragment != null)
            manager.beginTransaction().remove(fragment).commit();
    }
    

    我是否应该在 radioGroup.SetOnCheckedChangeListener 之外的任何时候调用它

    这取决于您要用于删除片段的逻辑/事件。

    【讨论】:

    • 首先感谢您的回复!它确实帮助我清除了我的removeFragments() 方法。我想我必须指定每个 Fragment 类型来删除它,而不是使用更通用的方法。不过,为了纠正您,如果我有一个 Fragment B 填充该 FrameLayout 并且我尝试将其转换为 Fragment A 之类的变量,则该方法将通过异常。但是使用您的方法,我将避免所有这些不必要的代码.在代码中的其他点调用该方法时,我仍然无法删除片段,我将对此进行更多检查。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-25
    • 1970-01-01
    • 1970-01-01
    • 2018-07-13
    • 1970-01-01
    • 2020-05-15
    相关资源
    最近更新 更多