0

我有一个 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()方法在此侦听器上使用时有效,但在代码中的其他点调用时无效?

4

1 回答 1

1

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

第一的

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

第二

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

这与后栈不同,后栈可以根据用户导航具有多个片段实例。

因此,removeFragments()实际上需要removeFragment()一次只需要删除一个片段。

根据文档,我猜您认为替换片段会将旧片段保留在占位符中:

调用 replace() 等效于在容器中调用 remove() 片段并将新片段添加到同一个容器。

第三

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

因此,in的逻辑removeFragments()可以简化为:

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

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

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

于 2021-09-11T04:54:13.963 回答