Управление жизненным циклом Android фрагментов в ViewPager и FragmentPagerAdapter

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

у меня есть FragmentActivity с ViewPager. The ViewPager использует нестандартный, но очень простой FragmentPagerAdapter. Каждый Fragment внутри ViewPager состоит из ExpandableListView. У меня также есть кнопка панели действий под названием "обновить". Пока предположим, что ViewPager есть только один Fragment. Действие создано, и Fragment ' s ExpandableListView заполняется (пока что так хорошо). При нажатии кнопки Обновить метод обработки в FragmentActivity перебирает список Fragments которые назначаются FragmentPagerAdapter и вызывает refresh() в каждом Fragment чтобы заполнить его ListView. Однако, когда ориентация устройства изменяется (например, от портрета к ландшафту), активность воссоздается, а также фрагменты. Нажатие кнопки "Обновить" теперь будет повторяться без инициализации Fragments.

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

  1. FragmentActivity.onCreate()
  2. FragmentActivity.setContentView()
  3. FragmentActivity.createPagerFragments()
  4. Fragment.onAttach()
  5. Fragment.onCreate()
  6. Fragment.onCreateView()
  7. Fragment.onActivityCreated()
  8. >
  9. FragmentActivity.onCreate()
  10. Fragment.onAttach()
  11. Fragment.onCreate()
  12. FragmentActivity.setContentView()
  13. FragmentActivity.createPagerFragments()
  14. Fragment.onCreateView()
  15. Fragment.onActivityCreated()
  16. >
  17. FragmentActivity.refresh()
  18. >

Итак, проблема, как я вижу оно, следующим образом: Когда Android повторно создает FragmentActivity и Views после изменения ориентации экрана (вызовы #9-15 выше), он создает новый Fragment объекты с их состоянием, восстановленным до исходного состояния. Тем не менее, эти, по-видимому, полностью управляются FragmentManager, а не FragmentPagerAdapter. Напротив, когда FragmentPagerAdapter воссоздается вместе с Fragments в деятельности onCreate метод (см. вызов #13)Fragments что вам назначили адаптер никогда их Fragment.onCreate() или Fragment.onCreateView() методы вызываются вообще. Поэтому, когда вызывается метод refresh () (см. #17), метод перебирает эти Fragments, которые не были инициализированы. Поэтому, когда они пытаются заполнить ExpandableListView переменной экземпляра представления NULL. Это следует ожидать, поскольку переменная экземпляра назначается только в Fragment.onCreateView() метод никогда не вызывается на эти Fragments.

Итак, мой вопрос: как правильно повторно использовать re-recreated (by Android) Fragments после того, как ориентация экрана изменилась, чтобы избежать создания новых, которые не инициализируются? Мне нужно иметь действительную ссылку на них, чтобы вызвать их метод refresh (), который заполняет их по требованию. В идеале, они также должны быть назначены на FragmentPagerAdapter как хорошо.

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

спасибо!

3 ответов


Это много читать, но после прочтения только введение и вопрос и имея опыт работы с FragmentStatePagerAdapter, который похож на FragmentPagerAdapter я могу сказать вам, что:

после вращения ваш адаптер будет автоматически прикреплять старые фрагменты. Таким образом, кажется, что, хотя адаптер создания активности воссоздается, FragmentManager, который является глобальным, и его экземпляр сохраняет восстановление активности, обнаружит, что новый FragmentStatePagerAdapter объединен с тем же ViewPager и запрашивает те же фрагменты и просто извлекает их из BackStack фрагмента.

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

вы увидите в своих журналах многие onCreate () и другие состояния регистрируются одновременно, потому что FragmentStatePagerAdapter всегда извлекает/создает min 3 фрагмента (за исключением случаев, когда вы устанавливаете, что они только 2 или 1), поэтому также после поворота экрана 3 фрагмента будут повторно прикреплены из backstack.

Я надеюсь, что это помогло.


Я считаю, что этот вопрос, о получении текущего фрагмента из ViewPager, поможет вам. Как уже отмечалось, фрагменты управляются фрагментом (состоянием)PagerAdapter, а не жизненным циклом действия или фрагмента.

  • при первом создании действия фрагменты возвращаются getItem метод. Этот метод вызывается только один раз на фрагмент, даже если действие воссоздается.
  • последующие времена, фрагменты возвращаются instantiateItem метод. Скорее всего, это то место, где вам нужно заполучить свои фрагменты и вызвать их методы обновления.

Как насчет добавления этого в тег Activity в манифесте:

android:configChanges="orientation"

или это для API 13 или выше

android:configChanges="orientation|screenSize" 

поэтому он не будет воссоздавать ваши фрагменты при изменении ориентации..