IllegalStateException: не может выполнить это действие после onSaveInstanceState с ViewPager - PullRequest
445 голосов
/ 28 сентября 2011

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

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.onKeyUp(Activity.java:2044)
at android.view.KeyEvent.dispatch(KeyEvent.java:2529)
at android.app.Activity.dispatchKeyEvent(Activity.java:2274)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1803)
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:1855)
at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1277)
at android.app.Activity.dispatchKeyEvent(Activity.java:2269)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1803)
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.widget.TabHost.dispatchKeyEvent(TabHost.java:297)
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:1855)
at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1277)
at android.app.Activity.dispatchKeyEvent(Activity.java:2269)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1803)
at android.view.ViewRoot.deliverKeyEventPostIme(ViewRoot.java:2880)
at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2853)
at android.view.ViewRoot.handleMessage(ViewRoot.java:2028)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:132)
at android.app.ActivityThread.main(ActivityThread.java:4028)
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:844)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
at dalvik.system.NativeStart.main(Native Method)

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

Для записи: у меня есть вкладка, и на каждой вкладке есть группа действий, переключающаяся между действиями.

Ответы [ 32 ]

0 голосов
/ 21 июня 2019

Транзакции фрагмента не должны выполняться после Activity.onStop()! Убедитесь, что у вас нет обратных вызовов, которые могли бы выполнить транзакцию после onStop().Лучше исправить причину, чем пытаться обойти проблему с помощью таких подходов, как .commitAllowingStateLoss()

0 голосов
/ 07 марта 2019

используйте remove () вместо popup (), если состояние сохранено.

   private void removeFragment() {
    FragmentManager fragmentManager = getSupportFragmentManager();
    if (fragmentManager.isStateSaved()) {
        List<Fragment> fragments = fragmentManager.getFragments();
        if (fragments != null && !fragments.isEmpty()) {
            fragmentManager.beginTransaction().remove(fragments.get(fragments.size() - 1)).commitAllowingStateLoss();
        }
    }
}
0 голосов
/ 13 февраля 2019

@ Джан Гомен В моем случае вызов SUPER решает проблему. Это кажется более правильным решением, чем commitAllowingStateLoss (), потому что это решает проблему, а не скрывает ее.

@Override
public void onRequestPermissionsResult(
     final int requestCode,
     @NonNull final String[] permissions, 
     @NonNull final int[] grantResults
) {
        super.onRequestPermissionsResult(requestCode,permissions, grantResults); //<--- Without this line crash 
        switch (requestCode) {
            case Constants.REQUEST_CODE_PERMISSION_STORAGE:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    onPermissionGranted(Constants.REQUEST_CODE_PERMISSION_STORAGE);
                }
                break;
        }

0 голосов
/ 12 декабря 2018

Если у вас произошел сбой с помощью метода popBackStack () или popBackStackImmediate (), попробуйте исправить с помощью:

        if (!fragmentManager.isStateSaved()) {
            fragmentManager.popBackStackImmediate();
        }

Это работает и для меня.

0 голосов
/ 03 марта 2016

Добавьте это в свою деятельность

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    if (outState.isEmpty()) {
        // Work-around for a pre-Android 4.2 bug
        outState.putBoolean("bug:fix", true);
    }
}
0 голосов
/ 18 мая 2018

Я знаю, что @Ovidiu Latcu принял принятый ответ, но через некоторое время ошибка все еще сохраняется.

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

Crashlytics все еще посылает мне это странное сообщение об ошибке.

Однако ошибка теперь возникает только в версии 7+ (Nougat). Мое исправление заключается в использовании commitAllowingStateLoss () вместо commit () во фрагменте транзакции.

Эта запись полезна для commitAllowingStateLoss (), и никогда больше не возникала проблема с фрагментами.

Подводя итог, принятый здесь ответ может работать на версиях до Nougat для Android.

Это может сэкономить кому-то несколько часов поиска.счастливых кодировок.<3 ура </p>

0 голосов
/ 13 июня 2018

У меня была точно такая же проблема. Это произошло из-за разрушения предыдущей деятельности. когда я поддержал предыдущую деятельность, она была уничтожена. Я поставил базовую активность (НЕПРАВИЛЬНО)

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    SpinnerCustom2.setFragmentManager(getSupportFragmentManager());
    onCreateDrawerActivity(savedInstanceState);
}

Я включил его в Пуск, это было ПРАВО

@Override
protected void onStart() {
    super.onStart();
    SpinnerCustom2.setFragmentManager(getSupportFragmentManager());

}
0 голосов
/ 01 апреля 2016

Я также сталкивался с этой проблемой, и проблема возникает каждый раз, когда меняется контекст вашего FragmentActivity (например, изменяется ориентация экрана и т. Д.). Так что лучшее решение для этого - обновить контекст с вашего FragmentActivity.

0 голосов
/ 09 февраля 2018

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

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        final View rootView = findViewById(android.R.id.content);
        if (rootView != null) {
            rootView.cancelPendingInputEvents();
        }
    }
}
0 голосов
/ 15 декабря 2017

Я закончил с созданием базового фрагмента и заставил все фрагменты в моем приложении расширить его

public class BaseFragment extends Fragment {

    private boolean mStateSaved;

    @CallSuper
    @Override
    public void onSaveInstanceState(Bundle outState) {
        mStateSaved = true;
        super.onSaveInstanceState(outState);
    }

    /**
     * Version of {@link #show(FragmentManager, String)} that no-ops when an IllegalStateException
     * would otherwise occur.
     */
    public void showAllowingStateLoss(FragmentManager manager, String tag) {
        // API 26 added this convenient method
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (manager.isStateSaved()) {
                return;
            }
        }

        if (mStateSaved) {
            return;
        }

        show(manager, tag);
    }
}

Затем, когда я пытаюсь показать фрагмент, я использую showAllowingStateLoss вместо show

вот так:

MyFragment.newInstance()
.showAllowingStateLoss(getFragmentManager(), MY_FRAGMENT.TAG);

Я пришел к этому решению из этого PR: https://github.com/googlesamples/easypermissions/pull/170/files

...