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