"Сбой доставки результата" - onActivityForResult


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

на LoginActivity, в случае успешного входа,

setResult(1, new Intent());

на SherlockFragmentActivity:

@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)
5 68

5 ответов:

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

вызов commitAllowingStateLoss() это скорее Хак, чем исправление. Потери государства-это плохо, и их следует избегать любой ценой. В то время, что , состояние активности / фрагмента может еще не быть восстановлено, и поэтому любые транзакции, которые происходят в течение этого времени, будут потеряны в результате. Это очень важная ошибка, которую необходимо устранить! (Обратите внимание, что ошибка происходит только тогда, когда ваш 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 s всегда совершаются после the Activity'S состояние было восстановлено в исходное состояние (onPostResume() гарантированно вызывается после Activityсостояние восстановлено).

Это похоже на ответ @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 и лямбда используйте этот:

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

в моем случае я столкнулся с теми же проблемами, потому что следующее

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();

}

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

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

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

просто двигаться:

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

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