транзакция фрагмента commit () после того, как был вызван action.onSaveInstanceState () - PullRequest
0 голосов
/ 08 мая 2018

В моем приложении у меня есть Activity, который содержит 3 Fragments. При первом создании Activity отображается Fragment 1. Далее все транзакции фрагментов будут выполнены после сетевой операции. Например: Fragment 1 имеет button для запроса к серверу, а когда результат готов, Fragment 1 использует listener для вызова метода, определенного внутри родительского activity, для замены fragment 1 с fragment 2. Это прекрасно работает, за исключением случаев, когда родительский элемент activity получает callback после того, как его состояние было сохранено onSaveInstanceState(). IllegalStateException брошен.

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

Я также беру пример, который нашел здесь , чтобы попытаться решить проблему. Этот пост предлагает всегда проверять, работает ли activity перед вызовом commit(). Поэтому я объявил переменную Boolean в родительском activity и установил ее значение в false в onPause() и true в onResume().

Обратный вызов родительской активности, вызываемый после завершения сетевых операций, выглядит примерно так: Kotlin код, где next - номер заменяющего fragment:

private fun changeFragment(next:Int){
 // get the instance of the next fragment
  val currentFragment = createFragment(next)
 // do other stuff here

 if(isRunning){
   // prepare a replace fragment transaction and then commit

   ft.commit()

 }else{

   // store this transaction to be executed when the activity state become running

}

}

Этот код работает нормально, и теперь я больше не получаю Exception, но мой вопрос: возможно, что onSaveInstanceState() вызывается после того, как я проверяю if(isRunning) и до того, как я вызываю ft.commit(), так что commit () происходит после того, как состояние активности было сохранено, вызывая IllegalStateException снова?

Я не уверен, что onSaveInstanceState() может прервать мой метод changeFragment() в любой момент времени. Возможно ли это?

Если такая возможность существует и мой код может быть прерван между if(isRunning) и ft.commit(), что я могу сделать? Это может быть решено добавлением блока try{}catch(){} следующим образом:

if(isRunning){
  try{
    ft.commit()
  }catch(ie:IllegalStateException){
    // store the transaction and execute it when the activity become running
  }
}else{
 // store the transaction and execute it when the activity become running
}

Ответы [ 3 ]

0 голосов
/ 08 мая 2018

onSaveInstanceState() не сможет прервать ваш метод, если ваш метод вызывается в основном потоке (UI).

Другой подход, облегчающий вашу жизнь, заключается в том, чтобы не использовать обратные вызовы, а вместо этого использовать реактивный шаблон, такой как MVVM. В этом шаблоне ваши Activity или Fragment подписываются на наблюдаемые, когда они заинтересованы, например, в ответы по сети и отмена подписки обычно выполняются в обратных вызовах жизненного цикла onStop или onPause, чтобы ваши методы никогда не вызывались после onSaveInstanceState. Для хорошего начала, проверьте официальный обзор LiveData .

0 голосов
/ 29 июля 2019

Это немного поздно, но с API 26+ мы можем использовать следующее, чтобы проверить, нужно ли нам делать обычный коммит или commitAllowingStateLoss ().

getSupportFragmentManager().isStateSaved();
0 голосов
/ 08 мая 2018

Сохраняете ли вы что-нибудь, когда меняете состояние? Если нет, то вы можете попробовать commitAllowingStateLoss().

...