【问题标题】:How do I fix Fragment already added in my code?如何修复代码中已添加的片段?
【发布时间】:2021-04-07 17:30:31
【问题描述】:

我从A fragment打开一个dialog fragment,当对话框片段关闭时, 我想同时从A fragment切换到B fragment

但我不断收到Fragment already added error

我正在使用show() 而不是replace() 来改变屏幕。

Fragment already added error 在网上很容易解决,但是 我的工作并不奇怪。

可能我的代码有问题,请告诉我问题出在哪里。

MainActivity.java

public class MainActivity extends AppCompatActivity {
    BottomNavigationView bottomNav;
    FragmentManager fm;
    FragmentTransaction transaction;
    Fragment curFrag;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bottomNav = findViewById(R.id.bottom_nav);

        bottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                fm = getSupportFragmentManager();
                transaction = fm.beginTransaction();
                curFrag = fm.getPrimaryNavigationFragment();
                String tag = String.valueOf(item.getItemId());
                int id = item.getItemId();

                if(curFrag != null) {
                    transaction.hide(curFrag);
                }

                Fragment fragment = fm.findFragmentByTag(tag);
                if(fragment == null) {
                    if(id == R.id.list)
                        fragment = new WorkoutListFragment();
                    transaction.add(R.id.content_layout, fragment, tag);
                }
                else {
                    transaction.show(fragment);
                }

                transaction.setPrimaryNavigationFragment(fragment);
                transaction.setReorderingAllowed(true);
                transaction.commitNow();
                return true;
            }
        });
    }

    // Method for screen switching
    public void onFragmentChanged() {
//        transaction = fm.beginTransaction();
        String tag = "WriteRoutine";

        curFrag = fm.getPrimaryNavigationFragment();
        if (curFrag != null) {
            transaction.hide(curFrag);
        }

        Fragment fragment = fm.findFragmentByTag(tag);

        if (fragment == null) {
            fragment = new WriteRoutineFragment();
            fragment.setArguments(curFrag.getArguments());
            transaction.add(R.id.content_layout, fragment, tag);
        } else {
            transaction.show(fragment);
        }

        transaction.setReorderingAllowed(true);
        transaction.commit();
    }
}

WorkoutListFragment.java(一个片段)

public class WorkoutListFragment extends Fragment {
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);

        getParentFragmentManager().setFragmentResultListener("result", this, new FragmentResultListener(){
            @Override
            public void onFragmentResult(@NonNull String requestKey, @NonNull Bundle result) {
                if(result != null)
                    WorkoutListFragment.this.setArguments(result);
                    titleData = result.getStringArrayList("title");
            }
        });
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.activity_workout_list, container, false);
        initViews(rootView);
        ((AppCompatActivity) getActivity()).setSupportActionBar((toolbar));

        return rootView;
    }

    @Override
    public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
        menu.clear();
        inflater = getActivity().getMenuInflater();
        inflater.inflate(R.menu.record_item_add, menu);
    }

    @Override // open dialog
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        BodyPartDialogFragment dialog = new BodyPartDialogFragment();
        dialog.show(getActivity().getSupportFragmentManager(), "BodyPartDialog");
        return true;
    }
}

DialogFragment.java

public class BodyPartDialogFragment extends DialogFragment {

    Button startBtn;
    ArrayList<String> bodypart_strData;
    int selectedNum;

    final static String TAG = "DialogFragment";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_body_part_dialog, null);
        startBtn = view.findViewById(R.id.check);
        
        // A D D
        startBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(selectedNum == 0){
                    Toast.makeText(getContext(), "Plaese select", Toast.LENGTH_SHORT).show();
                }
                else {
                    MainActivity activity = (MainActivity) getActivity();
                    Bundle result = new Bundle();
                    result.putStringArrayList("title", bodypart_strData);
                    getParentFragmentManager().setFragmentResult("result", result);
                    activity.onFragmentChanged();
                    dismiss();
                }
            }
        });

        return view;
}

【问题讨论】:

    标签: java android android-fragments android-dialogfragment


    【解决方案1】:

    在测试您的代码后,您只需在添加/替换片段之前重新实例化 transaction 对象。

    所以,你需要在onFragmentChanged()下面添加:

    transaction = getSupportFragmentManager().beginTransaction();
    

    这里是:

    // Method for screen switching
    public void onFragmentChanged() {
    
        String tag = "WriteRoutine";
    
        transaction = getSupportFragmentManager().beginTransaction(); // <<< THE CHANGE IS HERE
        curFrag = fm.getPrimaryNavigationFragment();
        if (curFrag != null) {
            transaction.hide(curFrag);
        }
    
        Fragment fragment = fm.findFragmentByTag(tag);
    
        if (fragment == null) {
            fragment = new WriteRoutineFragment();
            fragment.setArguments(curFrag.getArguments());
            transaction.add(R.id.content_layout, fragment, tag);
        } else {
            transaction.show(fragment);
        }
    
        transaction.setReorderingAllowed(true);
        transaction.commit();
    }
    

    【讨论】:

    • 非常感谢,所以我解决了。但我要问你一个问题。我将Transaction variable 声明为member。这是因为在onNavigation~~() 中它是通过片段管理器(beginTransaction())引用的。所以我认为我不需要在onFragmentChanged() 中再次执行 beginTransaction()。因为您已经在onNav~~() 函数中引用了事务,所以它将继续引用它。但我不太明白这是一个问题。你能解释一下吗?
    • 第一个事务时保存了Transaction局部变量状态的问题,但是你知道你可以在后栈中进行其他事务或从中清除碎片,这可以包括显示并关闭弹出对话框..因此活动中的本地成员事务变量将具有事务的旧状态;因此您需要使用交易的当前状态重新初始化它。感谢接受答案
    猜你喜欢
    • 2020-11-16
    • 2018-12-16
    • 2017-10-01
    • 2018-10-20
    • 1970-01-01
    • 2019-04-05
    • 2021-03-25
    • 1970-01-01
    • 2014-12-22
    相关资源
    最近更新 更多