Всплывает SplashScreen, когда экран устройства выключен [дубликат]

Функция base reshape работает отлично:

df <- data.frame(
  year   = c(rep(2000, 12), rep(2001, 12)),
  month  = rep(1:12, 2),
  values = rnorm(24)
)
df_wide <- reshape(df, idvar="year", timevar="month", v.names="values", direction="wide", sep="_")
df_wide

Здесь idvar - столбец классов, который разделяет строки, timevar - столбец классов, который должен быть широко представлен, v.names - это столбец, содержащий числовые значения, direction указывает широкий или длинный формат, а необязательный аргумент sep - это разделитель, используемый между именами классов timevar и v.names на выходе data.frame. Если нет idvar, создайте его перед использованием функции reshape():

df$id   <- c(rep("year1", 12), rep("year2", 12))
df_wide <- reshape(df, idvar="id", timevar="month", v.names="values", direction="wide", sep="_")
df_wide

Просто помните, что требуется idvar! Часть timevar и v.names проста. Выход этой функции более предсказуем, чем некоторые другие, поскольку все явно определено.

327
задан dcool 19 September 2011 в 10:50
поделиться

30 ответов

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

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

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

0
ответ дан Alecs 22 August 2018 в 17:27
поделиться
  • 1
    Проводка на просмотр будет запускать Runnable только после того, как представление было правильно выложено и нарисовано на экране; это часто означает, что сама деятельность полностью возобновлена, поэтому нет проблем – Mercato 4 December 2017 в 17:18

Прочтите http://chris-alexander.co.uk/on-engineering/dev/android-fragments-within-fragments/

статью. fragment.isResumed () помогает мне в onDestroyView без использования метода onSaveInstanceState.

2
ответ дан andep 22 August 2018 в 17:27
поделиться

Это происходит всякий раз, когда вы пытаетесь загрузить фрагмент, но действие изменило его состояние на 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
}
1
ответ дан Anonymous 22 August 2018 в 17:27
поделиться

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

В моем случае я использовал 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();
}
0
ответ дан Antilope 22 August 2018 в 17:27
поделиться

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

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

То, что я сделал, следующее:

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

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

Выполнять простые шаги:

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

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

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

fragmentTransaction.commitAllowingStateLoss();
17
ответ дан Basbous 22 August 2018 в 17:27
поделиться
  • 1
    Удаление метода супер сделало трюк, не могли бы вы объяснить, почему? Безопасно ли это удалить? – Bruce 6 February 2016 в 17:49
  • 2
    не удастся удалить super (), после этого вы потеряете другие данные conf! – deadfish 28 February 2016 в 21:27

вы можете использовать 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- может-не-perform.html

-1
ответ дан benka 22 August 2018 в 17:27
поделиться

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

dismissAllowingStateLoss()

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

18
ответ дан Brian Dilley 22 August 2018 в 17:27
поделиться

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

0
ответ дан chris 22 August 2018 в 17:27
поделиться

Это исправлено в 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 «» может вам пригодиться.

435
ответ дан Community 22 August 2018 в 17:27
поделиться
  • 1
    Вы должны использовать commitAllowingStateLoss () вместо commit () – meh 28 September 2012 в 11:04
  • 2
    Таким образом, не вызов супер в onSaveInstanceState остановит FragmentManager, который сможет сохранить состояние всех фрагментов и восстановить их. Это может вызвать проблемы с вращением. Кроме того, я только что попробовал другое дело о том, чтобы положить мусор в пакет, и это не имеет для меня никакого значения. Не уверен, как это было бы - ошибка, на которую вы ссылались в пакете поддержки, является исключением NullPointerException и не похоже на это исключение IllegalStateException ... – themightyjon 7 November 2012 в 18:48
  • 3
    @meh commitAllowingStateLoss() устраняет исключение. Он не защищает ваше приложение от случайной потери состояния. См. Это сообщение в блоге . – Alex Lockwood 21 August 2013 в 00:20
  • 4
    @AlexLockwood, так что из этого сообщения в блоге мы можем узнать, что мы должны делать все наши сетевые вызовы внутри фрагмента (и при необходимости отображать некоторый временной прогресс ui), и это единственный способ избежать этого исключения, когда это возможно, потому что commit вызывается после вызова асинхронного метода. – meh 21 August 2013 в 22:30
  • 5
    @Alex: классная статья, будет рекламировать ее много! :) – gunar 6 September 2013 в 09:37
  • 6
    Я действительно не решал проблему, но эта проблема не связана с фиксацией и commitAllowStateLoss. – oO_ox 17 August 2016 в 07:19

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

4
ответ дан DanielBarbarian 22 August 2018 в 17:27
поделиться
  • 1
    спасибо, что он исправил мою проблему и сэкономил мне время – Ahmed M 25 March 2017 в 21:39
  • 2
    Спасибо. Это решение решило проблему, используя commitAllowingStateLoss() вместо commit() – Chintak Patel 21 August 2017 в 06:51
  • 3

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

0
ответ дан DCS 22 August 2018 в 17:27
поделиться

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

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

3
ответ дан dols 22 August 2018 в 17:27
поделиться
  • 1
    Хотя изменения конфигурации (например, изменения ориентации) могут привести к этому исключению, они не являются основной причиной. – Alex Lockwood 15 September 2013 в 03:56

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

0
ответ дан Ganesh Kanna 22 August 2018 в 17:27
поделиться

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

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

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

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

  1. Для фрагментов и действий, которые не должны содержать информацию о состоянии, вызовите commitAllowStateLoss . Взято из документации: позволяет выполнить фиксацию после сохранения состояния активности. Это опасно, поскольку фиксация может быть потеряна, если действие необходимо восстановить позже из состояния, поэтому это должно использоваться только в тех случаях, когда состояние пользовательского интерфейса неожиданно изменяется на пользователя. Я думаю, это нормально, если фрагмент показывает информацию только для чтения. Или даже если они отображают редактируемую информацию, используйте методы обратных вызовов, чтобы сохранить отредактированную информацию.
  2. Сразу после совершения транзакции (вы только что назвали commit() ), сделайте вызов FragmentManager.executePendingTransactions() .

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

  1. Как упоминалось выше Овидиу Латцу, не вызывайте super.onSaveInstanceState(). Но это означает, что вы потеряете все состояние своей активности вместе с состоянием фрагментов.
  2. Переопределить onBackPressed и там вызывать только finish(). Это должно быть ОК, если приложение не использует API фрагментов; как в super.onBackPressed есть вызов FragmentManager#popBackStackImmediate().
  3. Если вы используете 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);
    }
}

Приветствия!

72
ответ дан gunar 22 August 2018 в 17:27
поделиться
  • 1
    Это похоже на ActionBarSherlock тоже, под Gingerbread, поэтому случай проверки Build Id кажется спорным ... :( – t0mm13b 28 February 2013 в 18:51
  • 2
    Кроме того, вы должны указать, что это не подходит для использования ABS. :) – t0mm13b 28 February 2013 в 19:08
  • 3
    @ t0mm13b: код выше означает мой проект, так как он не использует ни фрагменты, ни поддержку. FragmentActivity. Он работает на android.app.Activity, и поскольку несогласованность, вызывающая исключение, вызвана FragmentManager (уровень API 11 вверх), вот почему проверка ... Если вы считаете, что источник зла для вас тоже то же самое, не стесняйтесь для удаления чека. ABS - это другая история, поскольку она работает поверх пакета совместимости и реализации поддержки. FragmentActivity может использовать ту же реализацию FragmentManager и voila: та же проблема. – gunar 28 February 2013 в 23:29
  • 4
    @ t0mm13b: чтобы добавить больше, чем 600 символов, вам недостаточно исследовать, что действительно вызывает это для вас. Вы также должны понимать, что выше - уродливый взлом, и я не беру на себя никакой ответственности, если он работает или нет (для меня это было наилучшим решением, учитывая обстоятельства). Если вам нужно использовать его, дважды проверьте исходный код совместимости для имен переменных, поскольку они могут отличаться от стандартного пакета. Я бы надеялся, что эта проблема будет решена в следующих версиях пакета совместимости, но из опыта Android, есть мало шансов на успех ... – gunar 28 February 2013 в 23:34
  • 5
    Uhhh ... Это точно такая же проблема, как в этом сообщении об ошибке , который является точкой этого вопроса OP. Я согласен с моим комментарием - вы должны явно вставить отказ и сказать, что это не гарантировано, а также должно заявить, что вы не использовали фрагменты - в противном случае зачем беспокоиться о публикации ответьте! :) Просто говорю... – t0mm13b 28 February 2013 в 23:50

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

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

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

32
ответ дан HitOdessit 22 August 2018 в 17:27
поделиться
  • 1
    Привет, Funk, у меня есть вопрос, почему при вызове onBackPressed можно вызвать эту активность или фрагмент, если эта активность или фрагмент остановлены. Вышеприведенное исключение, по-видимому, генерируется из некоторого события пользовательского интерфейса (то есть нажатие клавиши BACK), однако я не могу выяснить связь между Async Task и Back. – dcool 9 November 2011 в 05:08
  • 2
    Так как вы можете сохранить переход фрагмента в состояние «назад», нажатие кнопки «Назад» может привести к тому, что вы сохраните обратный переход (так возвращаются старые фрагменты). onSaveInstanceState вызывается до того, как ваша активность будет уничтожена для восстановления ресурсов в системе, а не всегда после вызова onStop. Извините, это было не очень ясно в моем ответе. – FunkTheMonk 9 November 2011 в 11:38
  • 3
    Funk, но я не использую какие-либо фрагменты в своем приложении. Это могут быть фрагменты, используемые в собственном коде. Раньше я думал, что вы об этом говорите. – dcool 9 November 2011 в 12:33
  • 4
    У меня был AsyncTask со ссылкой на фрагмент. Проблема решена после удаления вызова super () из onSaveInstanceState и замены ссылки из моей AsyncTask на WeakReference & lt; Fragment & gt ;. – Buffalo 28 June 2012 в 16:31
  • 5
    @Buffalo Это определенно не решение проблемы. Вы всегда должны называть super.onSaveInstanceState(). – Alex Lockwood 16 August 2013 в 16:27

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

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

0
ответ дан jai 22 August 2018 в 17:27
поделиться

Я думаю, что состояние Lifecycle может помочь предотвратить такой крах, начиная с поддержки Android 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#isStateSaved ()

5
ответ дан Jamal 22 August 2018 в 17:27
поделиться

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

Согласно doc:

 * 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()
0
ответ дан JianxinLi 22 August 2018 в 17:27
поделиться

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

0
ответ дан Juan Mendez 22 August 2018 в 17:27
поделиться

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

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

2) onCreate, ALWAYS снова инициализируйте 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();
    }
}
7
ответ дан kurayami88 22 August 2018 в 17:27
поделиться
  • 1
    Почему в первую очередь используется менеджер фрагментов класса? – 0101100101 7 November 2014 в 13:17

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

26
ответ дан MJ.Ahmadi 22 August 2018 в 17:27
поделиться

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

0
ответ дан Murat 22 August 2018 в 17:27
поделиться

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

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

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

0
ответ дан Question 22 August 2018 в 17:27
поделиться

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

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

Я окружаю его с помощью

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

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

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

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

4
ответ дан Roger C S Wernersson 22 August 2018 в 17:27
поделиться
  • 1
    Тоже самое. Я решил переопределить метод show (FragmentManager manager, String tag), заменив «commit» на «commitAllowingStateLoss»; теряя что-то, потому что я не могу установить два частных атрибута диалога: mDismissed и mShownByMe. Но он работает каждый раз :) – Francesco Ditrani 28 April 2015 в 20:58
  • 2
    Я сделал альтернативное решение для DialogFragment, которое может избежать этого исключения: github.com/AndroidDeveloperLB/DialogShard – android developer 25 October 2016 в 08:10

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

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(null);
    .....
2
ответ дан silentBeep 22 August 2018 в 17:27
поделиться

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

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

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

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

5
ответ дан Ziem 22 August 2018 в 17:27
поделиться
  • 1
    Trues .. ловить исключение может избежать краха приложения, но поведение проблемы такие фрагменты остаются на экране или didnt получить добавить. – Marcos Vasconcelos 6 August 2013 в 20:14
  • 2
    держите прокрутку. истина где-то рядом – anil 12 August 2015 в 12:21

У меня возникла эта проблема. Но я думаю, что эта проблема не связана с 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();
    }
}
435
ответ дан Community 22 August 2018 в 17:27
поделиться
  • 1
    Вы должны использовать commitAllowingStateLoss () вместо commit () – meh 28 September 2012 в 11:04
  • 2
    Таким образом, не вызов супер в onSaveInstanceState остановит FragmentManager, который сможет сохранить состояние всех фрагментов и восстановить их. Это может вызвать проблемы с вращением. Кроме того, я только что попробовал другое дело о том, чтобы положить мусор в пакет, и это не имеет для меня никакого значения. Не уверен, как это было бы - ошибка, на которую вы ссылались в пакете поддержки, является исключением NullPointerException и не похоже на это исключение IllegalStateException ... – themightyjon 7 November 2012 в 18:48
  • 3
    @meh commitAllowingStateLoss() устраняет исключение. Он не защищает ваше приложение от случайной потери состояния. См. Это сообщение в блоге . – Alex Lockwood 21 August 2013 в 00:20
  • 4
    @AlexLockwood, так что из этого сообщения в блоге мы можем узнать, что мы должны делать все наши сетевые вызовы внутри фрагмента (и при необходимости отображать некоторый временной прогресс ui), и это единственный способ избежать этого исключения, когда это возможно, потому что commit вызывается после вызова асинхронного метода. – meh 21 August 2013 в 22:30
  • 5
    @Alex: классная статья, будет рекламировать ее много! :) – gunar 6 September 2013 в 09:37
  • 6
    Я действительно не решал проблему, но эта проблема не связана с фиксацией и commitAllowStateLoss. – oO_ox 17 August 2016 в 07:19

Я решил проблему с 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);
} 
5
ответ дан Ziem 22 August 2018 в 17:27
поделиться

Это самая глупая ошибка, с которой я столкнулся до сих пор. У меня было приложение Fragment, отлично работающее для API & lt; 11 и Force Closing в API> 11.

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

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

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

EDIT: после еще нескольких исследований, это известная ошибка в пакете поддержки.

Если вам нужно сохранить экземпляр и добавить что-то в свой 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 : Fragment Transactions & amp;

  • НИКОГДА commit() транзакции после onPause() на pre-Honeycomb и onStop() на post-Honeycomb
  • Будьте внимательны при совершении транзакций внутри методов жизненного цикла Activity. Используйте onCreate(), onResumeFragments() и onPostResume()
  • Избегайте выполнения транзакций внутри асинхронных методов обратного вызова
  • Используйте commitAllowingStateLoss() только в качестве последнего средства
435
ответ дан Community 22 August 2018 в 17:27
поделиться
  • 1
    Вы должны использовать commitAllowingStateLoss () вместо commit () – meh 28 September 2012 в 11:04
  • 2
    Таким образом, не вызов супер в onSaveInstanceState остановит FragmentManager, который сможет сохранить состояние всех фрагментов и восстановить их. Это может вызвать проблемы с вращением. Кроме того, я только что попробовал другое дело о том, чтобы положить мусор в пакет, и это не имеет для меня никакого значения. Не уверен, как это было бы - ошибка, на которую вы ссылались в пакете поддержки, является исключением NullPointerException и не похоже на это исключение IllegalStateException ... – themightyjon 7 November 2012 в 18:48
  • 3
    @meh commitAllowingStateLoss() устраняет исключение. Он не защищает ваше приложение от случайной потери состояния. См. Это сообщение в блоге . – Alex Lockwood 21 August 2013 в 00:20
  • 4
    @AlexLockwood, так что из этого сообщения в блоге мы можем узнать, что мы должны делать все наши сетевые вызовы внутри фрагмента (и при необходимости отображать некоторый временной прогресс ui), и это единственный способ избежать этого исключения, когда это возможно, потому что commit вызывается после вызова асинхронного метода. – meh 21 August 2013 в 22:30
  • 5
    @Alex: классная статья, будет рекламировать ее много! :) – gunar 6 September 2013 в 09:37
Другие вопросы по тегам:

Похожие вопросы: