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

У меня есть приложение для 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)  

Ответ 1

Это самая глупая ошибка, с которой я столкнулся. У меня было приложение 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(), и все отлично работает. Надеюсь, это сэкономит вам время.

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

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

@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 из того, что я помню. Но если у вас все еще есть проблемы с этим, вы MUST также читаете @AlexLockwood: Фрагментные транзакции и потеря активности в деятельности предприятия

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

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

Ответ 2

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

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

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

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

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

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

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

Не рекомендуется:

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

  • Переопределить onBackPressed и там вызывать только finish(). Это должно быть ОК, если приложение не использует API фрагментов; как в super.onBackPressed есть вызов FragmentManager#popBackStackImmediate().

  • Если вы используете API-интерфейс Fragments и состояние вашей активности важно/важно, вы можете попытаться позвонить с помощью 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);
    }
}

Ура!

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

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

dismissAllowingStateLoss()

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

Ответ 6

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

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

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

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

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

fragmentTransaction.commitAllowingStateLoss();

Ответ 7

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

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

Ответ 8

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

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

Что я сделал дальше:

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

Ответ 9

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

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

@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);
} 

Ответ 10

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

В методах добавления фрагментов:

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

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

Ответ 11

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

Претендент был вызовом DialogFragment.show().

Я окружаю его

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

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

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

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

Ответ 12

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

Ответ 13

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

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

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

Fragment.isStateSaved()

больше информации здесь https://developer.android.com/reference/android/support/v4/app/Fragment.html#isStateSaved()

Ответ 14

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

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

Ответ 15

У меня возникла эта проблема. Но я думаю, что эта проблема не связана с 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

Возможно, это произошло в следующих случаях

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

@Override
public void onBackPressed() {

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

Ответ 17

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

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

Ответ 18

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

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

Вы можете использовать transaction.commitAllowingStateLoss() вместо transaction.commit() для загрузки фрагмента, но вы можете потерять завершающую операцию фиксации.

или

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

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

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

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

if(mIsResumed){
 //load the fragment
}

Ответ 19

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

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

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

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

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

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

Ответ 20

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

В моем случае я использовал 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();
}

Ответ 21

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

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

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

Ответ 22

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

Ответ 24

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

Ответ 25

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

Ответ 26

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

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

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

Ответ 27

Вы можете вызвать функцию fragmentManager.popBackStackImmediate(); когда действие приостановлено. Активность не завершена, но приостановлена, а не на переднем плане. Вам нужно проверить, приостановлена ​​ли операция или нет до popBackStackImmediate().

Ответ 28

Спасибо @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()

Ответ 29

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

Ответ 30

вы можете использовать FragmentActivity.onStart перед popBackStackImmediate

вот так:

public void backStackFragment() {
    this.start();
    getFragmentManager().popBackStackImmediate();
}

public void start(){
    FragmentActivity a = getActivity();
    if(a instanceof DepositPlanPadActivity){
      ((DepositPlanPadActivity)a).onStart();
    }
    if(a instanceof SmallChangePlanPad){
            ((SmallChangePlanPad)a).onStart();
        }
        if(a instanceof UserCenterActivity){
            ((UserCenterActivity)a).onStart();
        }
    }

http://jorryliu.blogspot.com/2014/09/illegalstateexception-can-not-perform.html