Невозможно выполнить это действие после отображения onSaveInstanceState

Я получаю следующие отчеты о сбоях:

Фатальное исключение: java.lang.IllegalStateException: невозможно выполнить это действие после onSaveInstanceState в android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1832) в android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager. java:1850) в android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:643) в android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:603) в android.support.v4.app .DialogFragment.show(DialogFragment.java:143)

Этот следующий код вызывает сбой, для ясности я вырезал некоторый тривиальный код установки. Я прочитал об этой ошибке и, насколько я понимаю, .show() должен быть безопасным при взаимодействии с пользователем, таком как onClick(). Единственное, о чем я могу думать, это то, что query() занимает много времени, и пользователь переключается. Это разумное объяснение этой ошибки? Это мгновенно на моих устройствах даже с большой БД. Любые другие возможности? Спасибо!

    foldersButton.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            final List<String> paths = new ArrayList<>();

            try(Cursor c = getActivity().getContentResolver().query(Meta.CONTENT_URI,
                    new String[]{"DISTINCT " + Meta.PARENT}, null, null,
                    Meta.PARENT + " ASC"))
            {
                while (c != null && c.moveToNext())
                {
                    String path = c.getString(c.getColumnIndex(Meta.PARENT));

                    // We place the excluded folders at the end
                    if (!mExcludedFolders.contains(path))
                        paths.add(path);
                }
            }

            [setup...]

            int[] position = new int[2];
            foldersButton.getLocationOnScreen(position);
            FolderDialog dialog = FolderDialog.newInstance(
                    paths.toArray(new String[paths.size()]),
                    visible,
                    excluded,
                    position[0],
                    position[1]);
            dialog.setStyle(DialogFragment.STYLE_NO_TITLE, R.style.FolderDialog);

            [setup...]

            dialog.show(getFragmentManager(), TAG);
        }
    });

person Anthony    schedule 04.02.2017    source источник
comment
Вы нашли решение для этого фатального исключения.   -  person Rameshbabu    schedule 07.06.2017


Ответы (4)


Если этот ваш код находится внутри действия, оберните вызов show следующим образом:

if(!isDestroyed() && !isFinishing())

и если этот код находится внутри фрагмента, оберните вызов show с помощью:

if (isResumed() && !isRemoving())

Это более или менее решит проблему приземления в несовместимом состоянии пользовательского интерфейса.

person Dibzmania    schedule 04.02.2017
comment
Это не работает, если активность просто остановлена, но не уничтожена. - person fdermishin; 10.07.2018

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

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

Вы можете использовать одну логическую переменную isInForeground и устанавливать/сбрасывать ее в onResume и onPause соответственно.

 @Override
    protected void onPause() {
        super.onPause();
       isInForeground=false;
    }

    @Override
    protected void onResume() {
        super.onResume();
       isInForeground=true;
    }

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

if(isInForeground){
  dialog.show(getFragmentManager(), TAG);
}
person Nayan Srivastava    schedule 04.02.2017

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

Существует LoaderManager для приложения, использующего неправильный запрос, но я использовал существующий onLoadFinished для запуска асинхронного запроса, который будет обновлять структуру пути при любом изменении базы данных. Теперь, когда пользователь нажимает, диалоговое окно готово к работе.

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

person Anthony    schedule 04.02.2017

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

if(!isDestroyed()&&!isFinishing()&&isAppInForground(this)){
//add your fragment
}

Напишите код, чтобы проверить, находится ли ваше приложение на переднем плане или нет

 /**
         *
         * @param context
         * @return boolean
         * tells whether user is currently viewing app or not if not return false otherwise true
         */
        public static boolean isAppInForground(Context context){
            boolean isInForeground = false;
            ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

                List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();
                for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
                    if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                        for (String activeProcess : processInfo.pkgList) {
                            if (activeProcess.equals(context.getPackageName())) {
                                isInForeground = true;
                            }
                        }
                    }
                }

            return isInForeground;
        }
person Mansuu....    schedule 19.06.2017