【问题标题】:Commit already called error, while changing fragment提交已经调用错误,同时更改片段
【发布时间】:2016-12-14 11:26:49
【问题描述】:

我最近在授予访问外部存储的权限 (Android M) 时偶然发现了错误“在 onSaveInstanceState 后无法执行此操作”。 我根据this帖子(我想)解决并解决了这个问题。

现在我遇到了一个新的问题,因为我在尝试更改片段时遇到了错误“commit already called”

只要我想切换到某个片段(以讨论片段为例),我就会收到错误“提交已调用”,请参阅 logcat。

我已经在 stackoverflow 上搜索了一些解决方案,但我似乎看不出有什么问题,我知道有很多承诺但是在我的情况下如何处理呢? 有人可以帮帮我吗?

在讨论片段中调用:

public class DiscussionsActivity extends BaseActivity
{
..
  discussionsFragment = DiscussionsFragment.getInstance(id);
  changeContent(discussionsFragment, R.id.content, false); <---
..
}

基础活动:

public class BaseActivity extends AppCompatActivity {

    protected Fragment currentFragment;
    protected MainFragment mainFragment;
    private FragmentManager fragmentManager;
    private FragmentTransaction transaction;
    private boolean mReturningWithResult = false;

    public void changeContent(Fragment fragment, int content, boolean inBackStack) {
        InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
        try {
            inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
        } catch (Exception e) {
        }
        fragmentManager = getSupportFragmentManager();
        String newTag = ((Object) fragment).getClass().getName() + ":" + fragmentManager.getBackStackEntryCount();

        transaction = fragmentManager.beginTransaction().replace(content, fragment, newTag);

        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        if (inBackStack) {
            transaction.addToBackStack(fragment.getClass().getSimpleName());
        } else
            mReturningWithResult = true; <--- handle onSaveInstanceState error in onResume
            try {
                fragmentManager.popBackStackImmediate();
                transaction.commit();
            } catch (IllegalStateException ignored) {
                // There's no way to avoid getting this if saveInstanceState has already been called.
            }

        currentFragment = fragment;
    }

@Override
    public void onResume() {
        super.onResume();
        if (mReturningWithResult) {
            fragmentManager.popBackStackImmediate();

            if (currentFragment != mainFragment) {
                transaction.commit(); <---- HERE THE CRASH HAPPENS
            }
        }
        // Reset the boolean flag back to false for next time.
        mReturningWithResult = false;
    }

Logcat:

FATAL EXCEPTION: main
Process: some.com.app, PID: 17374
java.lang.RuntimeException: Unable to resume activity {some.com.app/some.com.app.UI.Discussion.DiscussionsActivity_}: java.lang.IllegalStateException: commit already called
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3103)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3134)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2481)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.IllegalStateException: commit already called
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:683)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:662)
at some.com.app.UI.Base.BaseActivity.onResume(BaseActivity.java:144) <--

【问题讨论】:

  • 每次您打算执行任意数量的 Fragment 操作时,都需要开始一个新的 FragmentTransaction。
  • 但这就是我在 changeContent 中所做的事情?您能否根据我的代码提供一个示例?

标签: android android-fragments fragmenttransaction fragmentmanager


【解决方案1】:

移除全局 FragmentTransaction 并在本地声明

public void changeContent(Fragment fragment, int content, boolean inBackStack) {
        InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
        try {
            inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
        } catch (Exception e) {
        }
        fragmentManager = getSupportFragmentManager();
        String newTag = ((Object) fragment).getClass().getName() + ":" + fragmentManager.getBackStackEntryCount();

        FragmentTransaction  transaction = fragmentManager.beginTransaction().replace(content, fragment, newTag);

        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        if (inBackStack) {
            transaction.addToBackStack(fragment.getClass().getSimpleName());
        } else
            mReturningWithResult = true; <--- handle onSaveInstanceState error in onResume
            try {
                transaction.commit();
            } catch (IllegalStateException ignored) {
                // There's no way to avoid getting this if saveInstanceState has already been called.
            }

        currentFragment = fragment;
    }

【讨论】:

  • Thx Nas 但问题在于 onResume,里面有什么?现在 MainActivity 根本没有显示。
【解决方案2】:

您可以在提交语句之后尝试使用相同的片段事务提交两次。如果之前的事务已经提交,则创建一个新的片段事务。

还建议确保commit() 使用调试点

public void changeContent(Fragment fragment, int content, boolean inBackStack) {
 ...........
 ...........
     try {
         fragmentManager.popBackStackImmediate();
         transaction.commit();
       } catch (IllegalStateException ignored) {
       // There's no way to avoid getting this if saveInstanceState has already been called.

 ...........
 ...........


      }


@Override
 public void onResume() {
     super.onResume();
      ...........
      ...........
       //This method would be called at second time.

       transaction.commit(); <---- HERE THE CRASH HAPPENS

        // Reset the boolean flag back to false for next time.
        mReturningWithResult = false;
      ...........
      ...........
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-21
    • 1970-01-01
    • 2021-08-09
    • 1970-01-01
    • 1970-01-01
    • 2016-10-29
    • 2012-11-08
    • 1970-01-01
    相关资源
    最近更新 更多