Intereting Posts
Почему AccountAuthenticator # getAuthToken () не вызван? Критерий не работает на службе android с отдельным процессом Ошибка EGL_BAD_MATCH Android Studio Что вам нужно передать v4.widget.DrawerLayout.isDrawerOpen () /. OpenDrawer () /. CloseDrawer () Как воспроизвести видео с YouTube API с помощью YouTubePlayerFragment? Использование ECC Curve25519 для шифрования / дешифрования данных в Java Получить историю транзакций с Android Pay через API? Android AlarmManager setExact () не является точным Android / Java Javadoc отсутствует после обновления Android SDK Android анимирует мою относительную компоновку снизу вверх и сверху вниз, используя трансляцию анимации при просмотре изображения. Как создать Raw-сокет в Android? Twitter приложение только аутентификация java android с twitter4j Как превратить базу данных MSSQL в базу данных SQLite для Android API Карт Google v2 SupportMapFragment внутри ScrollView – пользователи не могут прокручивать карту по вертикали Получить список пользователей ListView, которые не отображаются

Взлом Android Fragment View State Loss при использовании FragmentTransaction.replace ()

У меня довольно большая проблема, и я не совсем понимаю, что происходит. Я разрабатываю приложение, которое использует Fragments (из библиотеки поддержки), и использую FragmentTransaction.replace() чтобы поместить новые фрагменты в задний стек и заменить старый. Код выглядит следующим образом:

 FragmentManager fm = getSupportFragmentManager(); FragmentTransaction ft = ft.beginTransaction(); // Animations in my res/anim folder ft.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right); ft.replace(R.id.fragment_container, newFragment, tag); ft.addToBackStack(null); ft.commit(); 

Это успешно заменяет мой фрагмент. Моя проблема заключается в следующем. В одном фрагменте у меня есть список элементов, которые создаются из пользовательского ввода. Теперь, когда пользователь нажимает кнопку «Далее», а затем нажимает кнопку «Назад» (чтобы вернуться к списку), список пуст, потому что представление уничтожено. Теперь я отметил следующее:

  1. OnSaveInstanceState не вызывается. Я считаю, что это происходит потому, что это вызывается только, когда говорит родительская активность. Основываясь на документах: «Существует много ситуаций, когда фрагмент может быть в основном снесен (например, когда он помещен в задний стек без отображения пользовательского интерфейса), но его состояние не будет сохранено до тех пор, пока его собственная деятельность не должна фактически сохранять свое состояние . ". По-видимому, выполнение замены на FragmentTransaction не является одним из тех случаев. Кто-нибудь имеет подтверждение по этому или лучшему объяснению?
  2. SetOnRetainInstanceState (true) не помогает в этой ситуации. Опять же, я полагаю, что это связано с информацией из документов: «Контролируйте, сохраняется ли экземпляр фрагмента в процессе повторного создания активности (например, при изменении конфигурации)». Я не выполняю никаких действий по воссозданию активности, поэтому это бесполезно.

Итак, я думаю, мой главный вопрос: есть ли способ сохранить состояние View (просто сохранить фрагмент) при использовании replace ? Существует FragmentTransaction.add() , но есть и некоторые проблемы с этим. Один из них заключается в том, что анимация выхода не выполняется, поэтому анимация неверна. Другим является то, что новый фрагмент, который старый фрагмент (тот, который помещается в невидимое состояние), остается кликабельным. Например, если у меня есть ListFragment, и я помещаю фрагмент содержимого поверх этого с помощью добавления, я все равно могу щелкнуть элементы списка в ListFragment.

Solutions Collecting From Web of "Взлом Android Fragment View State Loss при использовании FragmentTransaction.replace ()"

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

 public void onViewStateRestored (Bundle savedInstanceState) { super.onViewStateRestored (savedInstanceState); setListAdapter(new ArrayAdapter(Activity, R.layout.nav_item, objects)); } 

Что странно, учитывая, что в документации указано, что этот метод вызывается после onActivityCreated но до onStart . Но кажется, что он также вызывается в другое время, потому что, когда самая последняя транзакция фрагмента удаляется из заднего стека, этот метод вызывается до отображения ранее замещенного фрагмента. Активность, которая владеет onViewStateRestored фрагментами, никоим образом не была приостановлена ​​или не затенена, поэтому в соответствии с документами onViewStateRestored не следует вызывать, поскольку только фрагменты были изменены. Но это все равно работает.

Похоже, вам просто нужно убедиться, что вы правильно реализовали onCreateView и onDestroyView. Ситуация, о которой вы описываете, по-видимому, указывает на то, что когда фрагмент списка помещается в задний стек (в результате транзакции замены), Android вызывает onDestroyView, чтобы освободить некоторые ресурсы. Однако, по-видимому, он не уничтожил фрагмент списка, потому что, когда вы возвращаете назад, вы возвращаете один и тот же экземпляр фрагмента.

Предполагая, что это правда, тогда, когда пользователь отбросит назад, Android вызовет onCreateView. Любое состояние, которое вы сохранили в переменных экземпляра фрагмента, все равно должно быть там, и все, что вам нужно сделать, это повторить отображение … возможно, установите адаптер в ListView или что угодно.

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