"Ошибка выполнения результата" - onActivityForResult

У меня есть LoginActivity (Вход пользователя). Это, в основном, его собственный Activity, который называется как диалог (чтобы выглядеть как диалог). Он появляется над SherlockFragmentActivity. Я хочу: если есть успешный вход в систему, для обновления представления должно быть два FragmentTransaction. Вот код:

В LoginActivity, если успешный вход в систему,

setResult(1, new Intent());

В SherlockFragmentActvity:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (resultCode == 1) {
        LoggedStatus = PrefActivity.getUserLoggedInStatus(this);
        FragmentTransaction t = MainFragmentActivity.this.getSupportFragmentManager().beginTransaction();
        SherlockListFragment mFrag = new MasterFragment();
        t.replace(R.id.menu_frame, mFrag);
        t.commit();

        // Set up Main Screen
        FragmentTransaction t2 = MainFragmentActivity.this.getSupportFragmentManager().beginTransaction();
        SherlockListFragment mainFrag = new FeaturedFragment();
        t2.replace(R.id.main_frag, mainFrag);
        t2.commit();
    }
}

Он сбой при первом фиксации с помощью этого LogCat:

E/AndroidRuntime(32072): Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
E/AndroidRuntime(32072):    at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1299)
E/AndroidRuntime(32072):    at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1310)
E/AndroidRuntime(32072):    at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:541)
E/AndroidRuntime(32072):    at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:525)
E/AndroidRuntime(32072):    at com.kickinglettuce.rate_this.MainFragmentActivity.onActivityResult(MainFragmentActivity.java:243)
E/AndroidRuntime(32072):    at android.app.Activity.dispatchActivityResult(Activity.java:5293)
E/AndroidRuntime(32072):    at android.app.ActivityThread.deliverResults(ActivityThread.java:3315)

Ответ 1

Прежде всего, вы должны прочитать мою сообщение в блоге для получения дополнительной информации (это говорит о том, почему это исключение происходит и что вы можете сделать, чтобы предотвратить его).

Вызов commitAllowingStateLoss() - это скорее взлом, чем исправление. Государственная потеря плохая и ее следует избегать любой ценой. Во время вызова onActivityResult() состояние активности/фрагмента может быть еще не восстановлено, и поэтому любые транзакции, которые происходят в течение этого времени, будут потеряны в результате. Это очень важная ошибка, которая должна быть решена! (Обратите внимание, что ошибка возникает только тогда, когда ваш Activity возвращается после того, как был убит системой... что, в зависимости от того, сколько памяти имеет устройство, иногда может быть редкими... так что такая ошибка не то, что очень легко уловить во время тестирования).

Попробуйте переместить транзакции в onPostResume() вместо этого (обратите внимание, что onPostResume() всегда вызывается после onResume() и onResume() всегда вызывается после onActivityResult()):

private boolean mReturningWithResult = false;

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    mReturningWithResult = true;
}

@Override
protected void onPostResume() {
    super.onPostResume();
    if (mReturningWithResult) {
        // Commit your transactions here.
    }
    // Reset the boolean flag back to false for next time.
    mReturningWithResult = false;
}

Это может показаться немного странным, но выполнение такого рода вещей необходимо для обеспечения того, чтобы ваш FragmentTransaction всегда выполнялся после того, как состояние Activity было восстановлено в исходное состояние (onPostResume() гарантированно будет вызвано после восстановления состояния Activity).

Ответ 2

Это похоже на ответ @Alex Lockwood, но с помощью Runnable:

private Runnable mOnActivityResultTask;

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    mOnActivityResultTask = new Runnable() {
        @Override
        public void run() {
            // Your code here
        }
    }
}

@Override
protected void onPostResume() {
    super.onPostResume();
    if (mOnActivityResultTask != null) {
        mOnActivityResultTask.run();
        mOnActivityResultTask = null;
    }
}

Если вы используете Android 3.0 и выше с lambdas, используйте это:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    mOnActivityResultTask = () -> {
        // Your code here
    }
}

Ответ 3

В моем случае я столкнулся с теми же проблемами из-за следующих

public void onBackPressed() {
    super.onBackPressed();
    setIntents();

}


private void setIntents(){
    Intent searchConstaints=new Intent();
    searchConstaints.putExtra("min",20);
    searchConstaints.putExtra("max",80);
    setResult(101,searchConstaints);
    finish();
}

Решено путем переустановки функции Вызовы внутри onBackPressed()

public void onBackPressed() {

    setIntents();
    super.onBackPressed();

}

Ответ 4

ваш логарифм четко говорит: "Невозможно выполнить это действие после onSaveInstanceState" - ваш Activity уже мертв в этой точке и не смог вернуть никаких результатов.

просто переместите:

Intent in = new Intent();
setResult(1, in);

к месту в вашем Activity, где он все еще жив, и все будет хорошо. и не забывайте finish() ваш Activity, чтобы доставить результат.

Ответ 5

Вы можете использовать ft.commitAllowingStateLoss() для решения этой проблемы.

Причина: ваш метод ft.commit() был переключен после onSaveInstanceState.