Получение исключения "IllegalStateException: не удается выполнить это действие после onSaveInstanceState"

У меня есть приложение Live Android, и с маркета я получил следующую трассировку стека, и я понятия не имею, почему это происходит, потому что это происходит не в коде приложения, а вызвано тем или иным событием из приложения (предположение)

Я не использую фрагменты, но есть ссылка на FragmentManager. Если какое-либо тело может пролить некоторый свет на некоторые скрытые факты, чтобы избежать этого типа проблемы:

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1109)
at android.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:399)
at android.app.Activity.onBackPressed(Activity.java:2066)
at android.app.Activity.onKeyDown(Activity.java:1962)
at android.view.KeyEvent.dispatch(KeyEvent.java:2482)
at android.app.Activity.dispatchKeyEvent(Activity.java:2274)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1668)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:1720)
at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1258)
at android.app.Activity.dispatchKeyEvent(Activity.java:2269)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1668)
at android.view.ViewRoot.deliverKeyEventPostIme(ViewRoot.java:2851)
at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2824)
at android.view.ViewRoot.handleMessage(ViewRoot.java:2011)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:132)
at android.app.ActivityThread.main(ActivityThread.java:4025)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:491)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)  

33 ответа

Это самая глупая ошибка, с которой я когда-либо сталкивался. У меня есть Fragment приложение отлично работает для API <11, и Force Closing по API> 11.

Я действительно не мог понять, что они изменили внутри Activity жизненный цикл в призыве к saveInstance Но вот как я решил это:

@Override
protected void onSaveInstanceState(Bundle outState) {
    //No call for super(). Bug on API Level > 11.
}

Я просто не звоню .super() и все отлично работает. Я надеюсь, что это сэкономит вам время.

РЕДАКТИРОВАТЬ: после некоторых дополнительных исследований, это известная ошибка в пакете поддержки.

Если вам нужно сохранить экземпляр и добавить что-то outStateBundle Вы можете использовать следующее:

@Override
protected void onSaveInstanceState(Bundle outState) {
    outState.putString("WORKAROUND_FOR_BUG_19917_KEY", "WORKAROUND_FOR_BUG_19917_VALUE");
    super.onSaveInstanceState(outState);
}

EDIT2: это также может произойти, если вы пытаетесь выполнить транзакцию после Activity ушел в фоновом режиме. Чтобы избежать этого, вы должны использовать commitAllowingStateLoss()

EDIT3: вышеупомянутые решения исправляли проблемы в ранних библиотеках support.v4 из того, что я помню. Но если у вас все еще есть проблемы с этим, вы ДОЛЖНЫ также прочитать Alex Lockwood: Потеря транзакций и активности фрагментов

Резюме из поста в блоге (но я настоятельно рекомендую вам прочитать его):

  • НИКОГДА commit() транзакции после onPause() на предварительных сотах, и onStop() на пост-соты
  • Будьте осторожны при совершении транзакций внутри Activity методы жизненного цикла. использование onCreate(), onResumeFragments() а также onPostResume()
  • Избегайте выполнения транзакций внутри методов асинхронного обратного вызова
  • использование commitAllowingStateLoss() только в крайнем случае

Поиск в исходном коде Android причин, по которым возникает эта проблема, дает флаг mStateSaved в FragmentManagerImpl класс (экземпляр доступен в Activity) имеет значение true. Значение true, когда задний стек сохраняется (saveAllState) при вызове из Activity#onSaveInstanceState, После этого вызовы из ActivityThread не сбрасывают этот флаг, используя доступные методы сброса из FragmentManagerImpl#noteStateNotSaved() а также dispatch(),

На мой взгляд, есть несколько доступных исправлений, в зависимости от того, что делает и использует ваше приложение:

Хорошие способы

Прежде всего: я бы рекламировал статью Алекса Локвуда. Тогда из того, что я сделал до сих пор:

  1. Для фрагментов и действий, которые не должны хранить никакой информации о состоянии, вызовите commitAllowStateLoss. Взято из документации:

    Позволяет выполнить коммит после сохранения состояния действия. Это опасно, потому что фиксация может быть потеряна, если впоследствии необходимо восстановить активность из ее состояния, поэтому ее следует использовать только в тех случаях, когда вполне допустимо непредвиденное изменение состояния пользовательского интерфейса для пользователя`. Я думаю, что это нормально использовать, если фрагмент показывает информацию только для чтения. Или даже если они показывают редактируемую информацию, используйте методы обратного вызова, чтобы сохранить отредактированную информацию.

  2. Сразу после завершения транзакции (вы только что позвонили commit()), позвоните FragmentManager.executePendingTransactions(),

Не рекомендуемые способы:

  1. Как упоминалось выше, Овидиу Латку, не звоните super.onSaveInstanceState(), Но это означает, что вы потеряете все состояние своей активности вместе с состоянием фрагментов.

  2. Override onBackPressed и там только звонок finish(), Это должно быть нормально, если ваше приложение не использует Fragments API; как в super.onBackPressed есть вызов FragmentManager#popBackStackImmediate(),

  3. Если вы используете API Fragments и состояние вашей активности важно / важно, то вы можете попытаться позвонить с помощью Reflection API FragmentManagerImpl#noteStateNotSaved(), Но это взлом, или можно сказать, что это обходной путь. Мне это не нравится, но в моем случае это вполне приемлемо, поскольку у меня есть код из унаследованного приложения, в котором используется устаревший код (TabActivity и неявно LocalActivityManager).

Ниже приведен код, который использует отражение:

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    invokeFragmentManagerNoteStateNotSaved();
}

@SuppressWarnings({ "rawtypes", "unchecked" })
private void invokeFragmentManagerNoteStateNotSaved() {
    /**
     * For post-Honeycomb devices
     */
    if (Build.VERSION.SDK_INT < 11) {
        return;
    }
    try {
        Class cls = getClass();
        do {
            cls = cls.getSuperclass();
        } while (!"Activity".equals(cls.getSimpleName()));
        Field fragmentMgrField = cls.getDeclaredField("mFragments");
        fragmentMgrField.setAccessible(true);

        Object fragmentMgr = fragmentMgrField.get(this);
        cls = fragmentMgr.getClass();

        Method noteStateNotSavedMethod = cls.getDeclaredMethod("noteStateNotSaved", new Class[] {});
        noteStateNotSavedMethod.invoke(fragmentMgr, new Object[] {});
        Log.d("DLOutState", "Successful call for noteStateNotSaved!!!");
    } catch (Exception ex) {
        Log.e("DLOutState", "Exception on worka FM.noteStateNotSaved", ex);
    }
}

Ура!

Такое исключение произойдет, если вы попытаетесь выполнить переход фрагмента после того, как ваш фрагмент активности onSaveInstanceState() вызывается.

Одна из причин, по которой это может произойти, это если вы оставите AsyncTask (или же Thread) работает, когда деятельность прекращается.

Любые переходы после onSaveInstanceState() Вызов может потенциально потеряться, если система восстановит активность для ресурсов и создаст ее позже.

Просто вызовите super.onPostResume() перед показом своего фрагмента или переместите свой код в метод onPostResume () после вызова super.onPostResume(). Это решит проблему!

Это также может произойти при звонке dismiss() на фрагменте диалога после того, как экран был заблокирован \ заглушен, а состояние экземпляра диалога Activity + было сохранено. Чтобы обойти этот вызов:

dismissAllowingStateLoss()

Буквально каждый раз, когда я закрываю диалог, я все равно больше не волнуюсь о его состоянии, так что это нормально - вы фактически не теряете ни одно состояние.

Краткое и рабочее решение:

Следуйте простым шагам:

Шаг 1: Переопределить состояние onSaveInstanceState в соответствующем фрагменте. И удалите супер метод из него.

@Override
public void onSaveInstanceState(Bundle outState) {
};

Шаг 2: Используйте CommitAllowingStateLoss(); вместо commit(); пока фрагмент операции.

fragmentTransaction.commitAllowingStateLoss();

Я думаю, что состояние жизненного цикла может помочь предотвратить такой сбой, начиная с поддержки Android lib v26.1.0, вы можете выполнить следующую проверку:

if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)){
  // Do fragment's transaction commit
}

или вы можете попробовать:

Fragment.isStateSaved()

дополнительная информация здесь https://developer.android.com/reference/android/support/v4/app/Fragment.html

Это сработало для меня... выяснил это сам... надеюсь, это поможет вам!

1) НЕ имеет глобальной "статической" FragmentManager / FragmentTransaction.

2) onCreate, ВСЕГДА снова инициализируйте FragmentManager!

образец ниже:-

public abstract class FragmentController extends AnotherActivity{
protected FragmentManager fragmentManager;
protected FragmentTransaction fragmentTransaction;
protected Bundle mSavedInstanceState;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mSavedInstanceState = savedInstanceState;
    setDefaultFragments();
}

protected void setDefaultFragments() {
    fragmentManager = getSupportFragmentManager();
    //check if on orientation change.. do not re-add fragments!
    if(mSavedInstanceState == null) {
        //instantiate the fragment manager

        fragmentTransaction = fragmentManager.beginTransaction();

        //the navigation fragments
        NavigationFragment navFrag = new NavigationFragment();
        ToolbarFragment toolFrag = new ToolbarFragment();

        fragmentTransaction.add(R.id.NavLayout, navFrag, "NavFrag");
        fragmentTransaction.add(R.id.ToolbarLayout, toolFrag, "ToolFrag");
        fragmentTransaction.commitAllowingStateLoss();

        //add own fragment to the nav (abstract method)
        setOwnFragment();
    }
}

Я всегда получал это, когда пытался показать фрагмент в методе onActivityForResult(), поэтому проблема была в следующем:

  1. Моя активность приостановлена ​​и остановлена, а это значит, что onSaveInstanceState() уже был вызван (для устройств до и сота и после сота).
  2. В случае какого-либо результата я сделал транзакцию, чтобы показать / скрыть фрагмент, который вызывает это IllegalStateException.

Я сделал следующее:

  1. Добавленное значение для определения того, было ли выполнено желаемое действие (например, фотографирование из camere - isPhotoTaken), - может быть логическим или целочисленным значением, в зависимости от того, сколько разных транзакций вам нужно.
  2. В переопределенном методе onResumeFragments() я проверил свое значение и после того, как мне понадобились транзакции фрагментов. В этом случае commit() не был выполнен после onSaveInstanceState, так как состояние было возвращено в методе onResumeFragments().

Я решил проблему с onconfiguration изменился. Хитрость заключается в том, что в соответствии с жизненным циклом активности андроида, когда вы явно называете намерение (намерение камеры или любое другое); в этом случае действие приостанавливается и вызывается onsavedInstance. При повороте устройства в другое положение, отличное от того, во время которого активность была активной; выполнение операций фрагмента, таких как фиксация фрагмента, приводит к исключению незаконного состояния. Есть много жалоб на это. Это что-то про управление жизненным циклом активности андроида и правильные вызовы методов. Чтобы решить эту проблему, я сделал это: 1-Переопределите метод onsavedInstance своей деятельности и определите текущую ориентацию экрана (книжную или альбомную), а затем установите ориентацию экрана до его приостановки. таким образом, действие блокирует поворот экрана для вашего действия, если оно было повернуто другим. 2-затем, переопределите метод действия onresume и установите режим ориентации сейчас на датчик, чтобы после вызова onsaved-метода он вызывал еще раз onconfiguration для правильной обработки вращения.

Вы можете скопировать / вставить этот код в вашу деятельность, чтобы справиться с ним:

@Override
protected void onSaveInstanceState(Bundle outState) {       
    super.onSaveInstanceState(outState);

    Toast.makeText(this, "Activity OnResume(): Lock Screen Orientation ", Toast.LENGTH_LONG).show();
    int orientation =this.getDisplayOrientation();
    //Lock the screen orientation to the current display orientation : Landscape or Potrait
    this.setRequestedOrientation(orientation);
}

//A method found in stackOverflow, don't remember the author, to determine the right screen orientation independently of the phone or tablet device 
public int getDisplayOrientation() {
    Display getOrient = getWindowManager().getDefaultDisplay();

    int orientation = getOrient.getOrientation();

    // Sometimes you may get undefined orientation Value is 0
    // simple logic solves the problem compare the screen
    // X,Y Co-ordinates and determine the Orientation in such cases
    if (orientation == Configuration.ORIENTATION_UNDEFINED) {
        Configuration config = getResources().getConfiguration();
        orientation = config.orientation;

        if (orientation == Configuration.ORIENTATION_UNDEFINED) {
        // if height and widht of screen are equal then
        // it is square orientation
            if (getOrient.getWidth() == getOrient.getHeight()) {
                orientation = Configuration.ORIENTATION_SQUARE;
            } else { //if widht is less than height than it is portrait
                if (getOrient.getWidth() < getOrient.getHeight()) {
                    orientation = Configuration.ORIENTATION_PORTRAIT;
                } else { // if it is not any of the above it will defineitly be landscape
                    orientation = Configuration.ORIENTATION_LANDSCAPE;
                }
            }
        }
    }
    return orientation; // return value 1 is portrait and 2 is Landscape Mode
}

@Override
public void onResume() {
    super.onResume();
    Toast.makeText(this, "Activity OnResume(): Unlock Screen Orientation ", Toast.LENGTH_LONG).show();
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
} 

У меня была такая же проблема, получение IllegalStateException, но замена всех моих вызовов commit () на commitAllowingStateLoss() не помогла.

Виновником был вызов DialogFragment.show().

Я окружаю это

try {
    dialog.show(transaction, "blah blah");
}
catch(IllegalStateException e) {
    return;
}

и это сделало это. ОК, я не могу показать диалог, но в этом случае все было в порядке.

Это было единственное место в моем приложении, где я сначала вызвал FragmentManager.beginTransaction (), но никогда не вызывал commit (), поэтому я не нашел его, когда искал "commit ()".

Самое смешное, что пользователь никогда не покидает приложение. Вместо этого убийца был рекламным объявлением AdMob.

У меня та же проблема в моем приложении. Я решил эту проблему, просто позвонив super.onBackPressed(); на предыдущем занятии и вызывая commitAllowingStateLoss() на текущий класс с этим фрагментом.

Я получил эту проблему. Но я думаю, что эта проблема не связана с commit и commitAllowStateLoss.

Следующее сообщение трассировки стека и исключения относится к commit().

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1341)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1352)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)

Но это исключение было вызвано onBackPressed()

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(Unknown Source)
at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(Unknown Source)
at android.support.v4.app.FragmentActivity.onBackPressed(Unknown Source)

Все они были вызваны checkStateLoss ()

private void checkStateLoss() {
    if (mStateSaved) {
        throw new IllegalStateException(
                "Can not perform this action after onSaveInstanceState");
    }
    if (mNoTransactionsBecause != null) {
        throw new IllegalStateException(
                "Can not perform this action inside of " + mNoTransactionsBecause);
    }

mStateSaved будет истинным после onSaveInstanceState.

Эта проблема встречается редко. Я никогда не сталкивался с этой проблемой. Я не могу повторить проблему.

Я нашел проблему 25517

Это могло произойти при следующих обстоятельствах

  1. Клавиша возврата вызывается после onSaveInstanceState, но до начала нового действия.

  2. используйте onStop() в коде

Я не уверен, в чем корень проблемы. Поэтому я использовал некрасивый способ.

@Override
public void onBackPressed() {

    try{
        super.onBackPressed();
    }catch (IllegalStateException e){
        // can output some information here
        finish();
    }
}

Мое решение этой проблемы было

Во фрагмент добавьте методы:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    ...
    guideMapFragment = (SupportMapFragment)a.getSupportFragmentManager().findFragmentById(R.id.guideMap);
    guideMap = guideMapFragment.getMap();
    ...
}

@Override
public void onDestroyView() {
    SherlockFragmentActivity a = getSherlockActivity();
    if (a != null && guideMapFragment != null) {
        try {
            Log.i(LOGTAG, "Removing map fragment");
            a.getSupportFragmentManager().beginTransaction().remove(guideMapFragment).commit();
            guideMapFragment = null;
        } catch(IllegalStateException e) {
            Log.i(LOGTAG, "IllegalStateException on exit");
        }
    }
    super.onDestroyView();
}

Может быть плохо, но не мог найти ничего лучше.

Другой способ решения проблемы жизненного цикла - использование последней выпущенной версии lifecycle-ktx с kotlin.

      lifecycleScope.launchWhenResumed {
    // your code with fragment or dialogfragment
}

Закрытие будет запущено после состояния возобновления, поэтому даже этот метод вызывается после остановки, он будет безопасно выполнен, когда придет следующее возобновление.

Вы также можете выбрать понравившийся

      lifecycleScope.launchWhenCreated
// or
lifecycleScope.launchWhenStarted

чтобы соответствовать вашей ситуации.

Код будет отменен, когда придет уничтожение.

Ссылка на документ Google:https://developer.android.com/kotlin/ktx#lifecycle

onSaveInstance будет вызываться, если пользователь поворачивает экран, чтобы он мог загружать ресурсы, связанные с новой ориентацией.

Возможно, что этот пользователь повернул экран, а затем нажал кнопку "Назад" (потому что также возможно, что этот пользователь шарил по телефону во время использования вашего приложения)

Та же проблема от меня, и после однодневного анализа всех статей, блогов и стекового потока я нашел простое решение. Ни в коем случае не используйте saveInstanceState, это условие с одной строкой кода. По коду фрагмента:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(null);
    .....

Это происходит всякий раз, когда вы пытаетесь загрузить фрагмент, но действие изменило свое состояние на onPause(). Это происходит, например, когда вы пытаетесь получить данные и загрузить их в действие, но к тому времени, когда пользователь нажал какую-то кнопку и перешел к следующему виду деятельности.

Вы можете решить это двумя способами

Для загрузки фрагмента вы можете использовать транзакцию mit.mitAllowingStateLoss() вместо транзакции транзакции (), но в итоге вы можете потерять выполненную операцию фиксации.

или же

Убедитесь, что при загрузке фрагмента действие возобновляется и не приостанавливается. Создайте логическое значение и проверьте, не переходит ли действие в состояние onPause().

@Override
public void onResume() {
    super.onResume();
    mIsResumed = true;
}

@Override
public void onPause() {
    mIsResumed = false;
    super.onPause();
}

затем при загрузке фрагмента проверьте, присутствует ли активность, и загружайте только тогда, когда активность находится на переднем плане.

if(mIsResumed){
 //load the fragment
}

Читайте http://chris-alexander.co.uk/on-engineering/dev/android-fragments-within-fragments/

статья. Проверка frag.isResumed() помогает мне в onDestroyView без использования метода onSaveInstanceState.

Спасибо @gunar, но я думаю, что есть лучший способ.

Согласно документу:

 * If you are committing a single transaction that does not modify the
 * fragment back stack, strongly consider using
 * {@link FragmentTransaction#commitNow()} instead. This can help avoid
 * unwanted side effects when other code in your app has pending committed
 * transactions that expect different timing.
 *
 * @return Returns true if there were any pending transactions to be
 * executed.
 */
public abstract boolean executePendingTransactions();

Так что используйте commitNow заменить:

fragmentTransaction.commit();
FragmentManager.executePendingTransactions()

Я заметил кое-что очень интересное. У меня в приложении есть возможность открыть галерею телефона, и устройство спрашивает, какое приложение использовать, там я нажимаю на серую область вдали от диалогового окна и вижу эту проблему. Я заметил, как моя деятельность переходит от onPause, onSaveInstanceState обратно к onResume, он не посещает onCreateView. Я делаю транзакции на OnResume. Итак, что я в итоге сделал, так это установил флаг, отменяющий onPause, но являющийся истинным для CreateView. если флаг имеет значение onResume, тогда делать onCommit, в противном случае commitAllowingStateLoss. Я мог бы продолжать и тратить столько времени, но я хотел проверить жизненный цикл. У меня есть устройство, которое является sdkversion 23, и у меня нет этой проблемы, но у меня есть другое, которое является 21, и там я вижу это.

В моем случае, с тем же исключением ошибки, я поместил onBackPressed() в runnable (вы можете использовать любое ваше представление):

myView.post(new Runnable() {
                    @Override
                    public void run() {
                        onBackPressed()
                    }
                });

Я не понимаю почему, но это работает!

Хорошо, после попытки всех вышеупомянутых решений без успеха (потому что в основном у меня нет транзакций).

В моем случае я использовал AlertDialogs и ProgressDialog в качестве фрагментов, которые иногда, при вращении, при запросе FragmentManager возникает ошибка.

Я нашел обходной путь, смешивающий много похожих постов:

Это трехэтапное решение, все сделано на вашей FragmentActivity (в данном случае его называют GenericActivity):

private static WeakReference<GenericActivity> activity = null; //To avoid bug for fragments: Step 1 of 3

@Override
protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    //To avoid bug for fragments: Step 2 of 3
    activity = new WeakReference<GenericActivity>(this);
}

@Override
public FragmentManager getSupportFragmentManager(){
    //To avoid bug for fragments: Step 3 of 3
    if (this == activity.get()) {
        return super.getSupportFragmentManager();
    }
    return activity.get().getSupportFragmentManager();
}

Я получал это исключение, когда нажимал кнопку "Назад", чтобы отменить выбор намерения на фрагменте карты. Я решил эту проблему, заменив код onResume()(где я инициализировал фрагмент и выполнял транзакцию) на onStart(), и теперь приложение работает нормально. Надеюсь, поможет.

Когда состояние Fragment или AppCompatActivity сохраняется с помощью onSaveInstanceState(), его пользовательский интерфейс считается неизменным до тех пор, пока не будет вызван ON_START. Попытка изменить пользовательский интерфейс после сохранения состояния может привести к несоответствиям в состоянии навигации вашего приложения, поэтому FragmentManager выдает исключение, если приложение запускает FragmentTransaction после сохранения состояния. Подробности смотрите в commit().

LiveData предотвращает этот пограничный случай из коробки, воздерживаясь от вызова своего наблюдателя, если связанный с наблюдателем жизненный цикл по крайней мере не ЗАПУЩЕН. За кулисами он вызывает isAtLeast(), прежде чем принять решение о вызове своего наблюдателя.

Мой вариант использования: я использовал слушателя во фрагменте, чтобы уведомить активность, что что-то произошло. Я сделал новый фрагмент коммита на методе обратного вызова. Это отлично работает в первый раз. Но при изменении ориентации активность воссоздается с сохраненным состоянием экземпляра. В этом случае фрагмент не создается снова означает, что фрагмент имеет прослушиватель, который является старой уничтоженной активностью. В любом случае метод обратного вызова будет вызван действием. Это идет к разрушенной деятельности, которая вызывает проблему. Решение состоит в том, чтобы сбросить слушателя во фрагменте с текущей активностью. Это решит проблему.

Вы можете вызывать фрагмент Manager.popBackStackImmediate(); когда активность приостановлена. Деятельность не закончена, но приостановлена ​​и не на переднем плане. Вам нужно проверить, приостановлена ​​ли активность перед popBackStackImmediate().

После небольшого исследования решение этой проблемы состоит в том, чтобы сделать ваши фрагменты коммитами в onresume.

Источник: https://wenchaojames.wordpress.com/2013/01/12/illegalstateexception-from-onactivityresult/

Когда я использую стартовую активность в одном фрагменте, я получу это исключение;

Когда я перехожу на использование startactivityforresult, исключение исчезает:)

Так что простой способ это исправить - использовать API startActivityForResult:)

Это исправлено в Android 4.2, а также в источнике библиотеки поддержки.[*]

Подробнее о причине (и обходных путях) см. Отчет об ошибках Google: http://code.google.com/p/android/issues/detail?id=19917

Если вы используете библиотеку поддержки, вам не придется беспокоиться об этой ошибке (надолго)[*]. Однако, если вы используете API напрямую (т.е. не используете FragmentManager библиотеки поддержки) и нацеливаетесь на API ниже Android 4.2, вам нужно попробовать один из обходных путей.

[*] На момент написания Android SDK Manager все еще распространял старую версию, в которой обнаружена эта ошибка.

Редактировать Я собираюсь добавить некоторые пояснения здесь, потому что я, очевидно, каким-то образом запутал того, кто отрицал этот ответ.

Есть несколько различных (но связанных) обстоятельств, которые могут вызвать это исключение. Мой ответ выше относится к конкретному случаю, обсуждаемому в вопросе, т.е. к ошибке в Android, которая впоследствии была исправлена. Если вы получаете это исключение по другой причине, это потому, что вы добавляете / удаляете фрагменты, когда этого не должно быть (после того, как состояния фрагментов были сохранены). Если вы находитесь в такой ситуации, то вам может пригодиться " Вложенные фрагменты - IllegalStateException" Не удается выполнить это действие после onSaveInstanceState " ".

Другие вопросы по тегам