2015-09-28 2 views
1

У меня есть слушатель в моей деятельности, замените фрагмент после завершения сетевого запроса в другом потоке. Так что слушатель вызова строки кода, как это:Когда использовать FragmentManager.isDestroyed()? Чтобы избежать исключения IllegalStateException?

getFragmentManager().beginTransaction().replace(R.id.container, fragment, fragmentTag).commit(); 

коммита,() в этой строке кода иногда бросает IllegalStateException. Согласно the docs,

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

Изучая это, я наткнулся на метод FragmentManager.isDestroyed(). Javadocs читает:

Возвращает true, если заключительный вызов Activity.onDestroy() был выполнен в Activity FragmentManager, поэтому данный экземпляр теперь мертв.

Я предполагаю, что я немного смущен в связи с тем, что экземпляр Activity FragmentManager был мертв. Когда мы должны использовать FragmentManager.isDestroyed()? Проверял бы его перед выполнением замены FragmentTransaction, избегая исключения IllegalStateException?

+0

Вы должны опубликовать свою ошибку LogCat –

+0

я испытывал то же самое ... и я считаю, что это совершенно верно: во всех моих случаях, когда FragmentManager.isDestroyed() возвращает значение ИСТИНА, в FragmentTransaction.commit () выкинет исключение IllegalStateException. В самом деле, первая проверка .isDestroyed() поможет вам избежать исключения, но вы также не получите транзакцию с фрагментами. – alpartis

+0

@alpartis Я добавлю несколько лучших протоколов и посмотрю, вернет ли FragmentManager.isDestroyed() true, когда я получу исключение IllegalStateException. Ваш комментарий кажется достаточно хорошим, чтобы быть ответом. Если вы опубликуете его как один, и никто не опубликует лучшего, я приму его. – pumpkinpie65

ответ

1

Мой код выглядит примерно следующим образом. Когда выполняется, все работает, и мой желаемый фрагмент отображается, или я получаю сообщение журнала, указывающее, что .isDestroyed() было истинным. Если я удалю проверку на .isDestroyed(), то ft.commit() выкинет IllegalStateException.

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

import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragementTransaction; 

public class CallingCard extends Fragment 
{ 
    // ... some stuff for my fragment ... 
} 

public class MyFragment extends Fragment 
{ 
    public void showCallingCard() { 
     CallingCard callingCard = new CallingCard(); 
     FragmentManager fm = parent.getSupportFragmentManager(); 

     // ensure serialization of fragment transactions 
     fm.executePendingTransactions(); 

     if (!fm.isDestroyed()) { 
      // attempt to display fragment 
      FragementTransaction ft = fm.beginTransaction(); 
      ft.replace(R.id.fragPlaceHolder, callingCard); 
      ft.commit(); 
     } else { 
      Log.e("tag", "fm.isDestroyed() was true"); 
     } 
    } 
} 
+0

В моем случае Фрагменты не были должным образом/полностью очищены от предыдущего использования, но их методы '.Destroy()' и т. Д. Были вызваны.Впоследствии, когда мой фрагмент был представлен в 2-й раз, внутренние переменные состояния были полностью удалены (это технический термин), и моя транзакция фрагмента не удалась, поскольку Android все еще считал, что содержащийся фрагмент все еще уничтожен (как указано в результате ' .isDestroyed() '). – alpartis

+0

Запуск некоторых данных из моих журналов, и я все еще получаю сбой, и похоже, что 'fm.isDestroyed()' возвращает 'false'. – pumpkinpie65

+0

Android не обязательно обрабатывает операции фрагмента точно так, как вы думаете во всех случаях. В некоторых случаях для обеспечения правильной сериализации требуется некоторая грубая сила. Добавьте вызов '.executePendingTransactions()' перед началом новой транзакции. Я попытаюсь обновить свой ответ выше, чтобы отразить это. – alpartis

0

Поддержание флага, чтобы узнать текущее состояние деятельности. Проверьте состояние onPause.

Не делайте транзакции диспетчера фрагментов после того, как действие переходит в состояние onPause. ЭТО РАБОТАЕТ ДЛЯ МЕНЯ .. !!!

@Override 
protected void onPause() { 
    super.onPause(); 
    isPaused = true; 

} 

@Override 
protected void onResume() { 
    super.onResume(); 
    isPaused = false; 
} 

// проверяем флаг isPaused.

if (!isPaused) { 
     fragmentManager.popBackStack(fragment.getClass().getName(), FragmentManager.POP_BACK_STACK_INCLUSIVE); 
     fragmentManager.beginTransaction() 
       // .setCustomAnimations(android.R.anim.fade_in,android.R.anim.fade_out) 
       .replace(R.id.container, fragment) 
       .commitAllowingStateLoss(); 
    } 

 Смежные вопросы

  • Нет связанных вопросов^_^