Управление жизненным циклом 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
.
я знаю, что я довольно расплывчато, особенно без образца кода, но, пожалуйста, потерпите меня. Я проследил проблему и вызовы методов следующим образом с самого начала приложения/действия:
FragmentActivity.onCreate()
FragmentActivity.setContentView()
-
FragmentActivity.createPagerFragments()
Fragment.onAttach()
-
Fragment.onCreate()
-
Fragment.onCreateView()
-
Fragment.onActivityCreated()
- >
FragmentActivity.onCreate()
Fragment.onAttach()
Fragment.onCreate()
FragmentActivity.setContentView()
FragmentActivity.createPagerFragments()
Fragment.onCreateView()
Fragment.onActivityCreated()
- >
-
FragmentActivity.refresh()
- >
Итак, проблема, как я вижу оно, следующим образом:
Когда 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"
поэтому он не будет воссоздавать ваши фрагменты при изменении ориентации..