Я пытался выяснить, что такое правильное управление Фрагментами в FragmentActivity
с ViewPager
. Прежде чем вдаваться в подробности, краткое изложение проблемы, с которой я столкнулся, следующее:
У меня есть FragmentActivity
с ViewPager
. ViewPager
использует пользовательский, но очень простой FragmentPagerAdapter
. Каждый Fragment
внутри ViewPager
содержит ExpandableListView
. У меня также есть кнопка панели действий под названием "Обновить". Пусть теперь ViewPager
имеет только один Fragment
. Действие создается, а Fragment
ExpandableListView
заполняется (пока что так хорошо). Когда нажата кнопка "Обновить", метод обработки в FragmentActivity
выполняет итерацию по списку Fragments
, которые назначаются FragmentPagerAdapter, и вызывает refresh()
на каждом Fragment
, чтобы заполнить свой ListView. Однако, когда ориентация устройства изменяется (например, от портрета к пейзажу), активность воссоздается, а также фрагменты. Нажатие кнопки "Обновить" теперь будет перебирать не инициализированный Fragments
.
Я знаю, что я довольно расплывчатый, особенно без образца кода, но, пожалуйста, несите меня. Я проследил проблему и вызовы метода следующим образом с начала приложения/действия:
-
FragmentActivity.onCreate()
-
FragmentActivity.setContentView()
-
FragmentActivity.createPagerFragments()
< - это создает ArrayList of Fragments и присваивает их новому FragmentPagerAdapter, который, в свою очередь, назначен ViewPager. -
Fragment.onAttach()
-
Fragment.onCreate()
< - ничего особенного здесь, просто вызов метода super. -
Fragment.onCreateView()
< - ничего особенного здесь, просто раздувание макета -
Fragment.onActivityCreated()
< - ничего здесь тоже. - < < Все хорошее, ориентация меняется здесь →
-
FragmentActivity.onCreate()
-
Fragment.onAttach()
-
Fragment.onCreate()
-
FragmentActivity.setContentView()
-
FragmentActivity.createPagerFragments()
-
Fragment.onCreateView()
-
Fragment.onActivityCreated()
- < < Кнопка "Обновить" нажата →
-
FragmentActivity.refresh()
< - итерации по вновь созданным фрагментам из # 13 (не для Android!). - < < Crash: NullPointerException для mExpandableListView в фрагменте. →
Таким образом, проблема, как я вижу, заключается в следующем:
Когда 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
.
Итак, мой вопрос: как правильно сделать повторное использование повторно воссозданного (Android) Fragments
после изменения ориентации экрана, чтобы избежать создания новых, которые не Не инициализироваться? Мне нужно иметь действительную ссылку на них, чтобы вызвать их метод refresh(), который заполняет их по требованию. В идеале они также должны быть привязаны к FragmentPagerAdapter
.
Надеюсь, я четко описал проблему, и причина, по которой я не привел пример кода, заключается в том, что проблема (как видно) не от самого кода, а от довольно неправильного (похожего) создание фрагментов, а не повторное использование. Но если нужно, я могу дать вам пример кода, я просто через это будет понятнее.
Спасибо!