Android FragmentTransaction已经调用了commit

50

我的错误:

java.lang.IllegalStateException:已调用提交

我的代码:

final FragmentTransaction fragmentTransaction =getFragmentManager().beginTransaction();

f1_fragment  = new F1_Fragments();
f2_fragment = new F2_Fragments();

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            parent.getItemAtPosition(position);

            if(position==0){
                fragmentTransaction.replace(android.R.id.content, f1_fragment);
            }else{
                fragmentTransaction.replace(android.R.id.content, f2_fragment);
            }

            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.commit();
        }
    });

8
如果您想再次提交,请注意您已经对该交易做了一次提交,需要开始一个新的交易。代码片段:fragmentTransaction = getFragmentManager().beginTransaction(); - tyczj
7个回答

71

您正在 OnItemClickListener 外开始 FragmentTransaction。因此,每次用户在 ListView 中点击一个项目时,您都会尝试 commit() 一个单独的 FragmentTransaction。

每当您打算执行任何数量的 Fragment 操作时,都需要开始一个新的 FragmentTransaction。

一个简单的修复方法如下:

f1_fragment  = new F1_Fragments();
f2_fragment = new F2_Fragments();

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        FragmentTransaction fragmentTransaction =getFragmentManager().beginTransaction();

        parent.getItemAtPosition(position);

        if(position==0){
            fragmentTransaction.replace(android.R.id.content, f1_fragment);
        }else{
            fragmentTransaction.replace(android.R.id.content, f2_fragment);
        }

        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();
    }
});

有没有最好的方法来实现这个?我正在SlidingMenu中实现Listview。 - JPs
从我所看到的,你使用的模式看起来很好。 - Bryan Herbst
它对我有效。我非常感谢你的帮助。谢谢。 - H.Gheisari

11
你可以使用这种方法相互替换片段,只需调用此方法。
这些是否是全局的?
YourFragment1 frg1 = new   YourFragment1 ();    
YourFragment2 frg1 = new   YourFragment2 (); 

然后通过调用它来实现

openFragment(frg1); 

或者
  openFragment(frg2);

OpenFragment:

  private void openFragment(final Fragment fragment)   {
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction transaction = fragmentManager.beginTransaction();        
    transaction.replace(R.id.container, fragment);
    transaction.addToBackStack(null);
    transaction.commit();

}

谢谢,同时将“fragmentManager”设置为私有字段是一个更好的主意 :) - Ali Sherafat

7

看这个场景

我需要在每次列表项被点击时添加新的片段。只需在每个项目点击时 初始化片段事务 即可。

switch (v.getId()) {

                case R.id.tvaddExpense:

                    fragmentTransaction = getFragmentManager().beginTransaction();
                    fragmentTransaction.add(R.id.containerFucntionsList, new Fragment1());
                    fragmentTransaction.addToBackStack(null);
                    fragmentTransaction.commit();
                    break;

                case R.id.relEvents:
                    fragmentTransaction = getFragmentManager().beginTransaction();
                    fragmentTransaction.replace(R.id.containerFucntionsList, new Fragment2());
                    fragmentTransaction.addToBackStack(null);
                    fragmentTransaction.commit();
                    break;
            } 

6
我曾经遇到过类似的问题,通过创建FragmentTransaction新实例来解决了它。
只需在每次添加/替换片段之前添加以下即可。
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();

希望这能帮到你。

5
错误
java.lang.IllegalStateException: commit already called
该错误提示表明,在第一次调用commit()后,FragmentTransaction已经完成,您再次调用commit()会导致重复完成。因此,会导致FragmentTransaction处于非法状态。
根据您的代码,您正在使用相同的FragmentTransaction来更改片段。然而,在第一次commit()调用之后,FragmentTransaction已经完成,您需要重新开始它才能对Fragments执行任何操作。
您可以将ClickListner更改为:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override

    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            fragmentTransaction = getSupportFragmentManager().beginTransaction();   

            parent.getItemAtPosition(position);

            if(position==0){
                fragmentTransaction.replace(android.R.id.content, f1_fragment);
            }else{
                fragmentTransaction.replace(android.R.id.content, f2_fragment);
            }

            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.commit();
        }
    });

我希望这能解决你的疑虑。

4
每次添加一个片段时,您必须单独定义一个FragmentTransAction对象:
     switch (position){
                case 0:
                    FragmentTransaction fragmentTransaction1 = getSupportFragmentManager().beginTransaction();
                    fragmentTransaction1.replace(R.id.parentOfMenu, new FragmentHome());
                    fragmentTransaction1.commit();

                    break;
                case 1:
                    FragmentTransaction fragmentTransaction2 = getSupportFragmentManager().beginTransaction();
                    fragmentTransaction2.replace(R.id.parentOfMenu, new FragmentMedia());
                    fragmentTransaction2.commit();

                    break;

                case 2:
                    FragmentTransaction fragmentTransaction3 = getSupportFragmentManager().beginTransaction();
                    fragmentTransaction3.replace(R.id.parentOfMenu, new FragmentChart());
                    fragmentTransaction3.commit();

                    break;

                case 3:
                    FragmentTransaction fragmentTransaction4 = getSupportFragmentManager().beginTransaction();
                    fragmentTransaction4.replace(R.id.parentOfMenu, new FragmentProfile());
                    fragmentTransaction4.commit();

                    break;
            }

0

在调用commit()并再次替换片段后,我解决了这个问题,你应该从此处开始。

fragmentTransaction = fragmentManager.beginTransaction();

if(position==0){
     fragmentTransaction.replace(android.R.id.content, f1_fragment);
 else{
     fragmentTransaction.replace(android.R.id.content, f2_fragment);
 }

 fragmentTransaction.addToBackStack(null);
 fragmentTransaction.commit();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接