В чем разница между FragmentPagerAdapter
и FragmentStatePagerAdapter
?
О FragmentPagerAdapter
гугле говорит:
Эта версия пейджера лучше всего подходит для использования, когда есть несколько статических фрагментов, которые нужно пролистать, например, набор вкладок. Фрагмент каждой страницы, которую пользователь посещает, будет храниться в памяти, хотя его иерархия просмотра может быть разрушена, если она не видна. Это может привести к использованию значительного объема памяти, поскольку экземпляры фрагмента могут удерживать произвольное количество состояния. Для больших наборов страниц, рассмотрим
FragmentStatePagerAdapter
.
И о FragmentStatePagerAdapter
:
Эта версия пейджера более полезна, когда имеется большое количество страниц, и работает больше как представление списка. Когда страницы не видны пользователю, весь их фрагмент может быть уничтожен, сохраняя только сохраненное состояние этого фрагмента. Это позволяет пейджеру удерживать гораздо меньше памяти, связанной с каждой посещаемой страницей, по сравнению с
FragmentPagerAdapter
затратами на потенциально большие издержки при переключении между страницами.
Так что у меня всего 3 фрагмента. Но все они являются отдельными модулями с большим объемом данных.
Fragment1
обрабатывает некоторые данные (которые вводят пользователи) и передает их через активность Fragment2
, которая является простой ListFragment
. Fragment3
также ListFragment
.
Итак, мои вопросы : какой адаптер я должен использовать? FragmentPagerAdapter
или FragmentStatePagerAdapter
?
FragmentPagerAdapter
иFragmentStatePagerAdapter
но чтоFragmentStateAdapter
?Ответы:
Как говорят в документах, думай об этом так. Если бы вы делали такое приложение, как программа для чтения книг, вы не захотите загружать все фрагменты в память сразу. Вы хотели бы загрузить и уничтожить,
Fragments
когда пользователь читает. В этом случае вы будете использоватьFragmentStatePagerAdapter
. Если вы просто отображаете 3 «вкладки», которые не содержат много тяжелых данных (напримерBitmaps
), тоFragmentPagerAdapter
вам это может подойти. Также имейте в виду, чтоViewPager
по умолчанию загружаются 3 фрагмента в память. Первое, о которомAdapter
вы упомянули, может разрушитьView
иерархию и перезагрузить ее, когда это необходимо, второеAdapter
только сохраняет состояниеFragment
и полностью уничтожает его, если пользователь затем возвращается на эту страницу, состояние восстанавливается.источник
FragmentPagerAdapter
чтобы его использовать.FragmentPagerAdapter
заключается в том, что переключение между фрагментами может быть намного быстрее, поскольку реальныеFragment
объекты не нужно каждый раз перестраивать. С другой стороны, это привело бы к использованию большего количества памяти, содержащей объекты фрагментов в памяти.viewPager.setOffscreenPageLimit(2)
.FragmentPagerAdapter
сохраняет весь фрагмент в памяти и может увеличить объем памяти, если в нем используется большое количество фрагментовViewPager
.В отличие от своего родного брата,
FragmentStatePagerAdapter
хранит только фрагменты сохраненного экземпляра и уничтожает все фрагменты, когда они теряют фокус.Поэтому
FragmentStatePagerAdapter
следует использовать, когда нам нужно использовать динамические фрагменты, такие как фрагменты с виджетами, поскольку их данные могут храниться в.savedInstanceState
Также это не повлияет на производительность, даже если имеется большое количество фрагментов.Напротив, его родной брат
FragmentPagerAdapter
должен использоваться, когда нам нужно сохранить весь фрагмент в памяти.Когда я говорю, что весь фрагмент хранится в памяти, это означает, что его экземпляры не будут уничтожены и создадут накладные расходы памяти. Поэтому рекомендуется использовать
FragmentPagerAdapter
только при небольшом количестве фрагментовViewPager
.Было бы еще лучше, если бы фрагменты были статическими, поскольку в них не было бы большого количества объектов, экземпляры которых будут сохранены.
Чтобы быть более подробно,
FragmentStatePagerAdapter:
с
FragmentStatePagerAdapter
, ваш ненужный фрагмент уничтожен. Транзакция обязана полностью удалить фрагмент из вашей деятельностиFragmentManager
.Состояние in
FragmentStatePagerAdapter
исходит из того факта, что оно спасет ваш фрагментBundle
отsavedInstanceState
момента его уничтожения. Когда пользователь вернется назад, новый фрагмент будет восстановлен с использованием состояния фрагмента.FragmentPagerAdapter:
По сравнению
FragmentPagerAdapter
ничего не делает. Когда фрагмент больше не нужен.FragmentPagerAdapter
звонкиdetach(Fragment)
по транзакции вместоremove(Fragment)
.Это уничтожение является представлением фрагмента, но оставляет экземпляр фрагмента живым.
FragmentManager
Таким образом, созданные фрагментыFragmentPagerAdapter
никогда не уничтожаются.источник
Вот журнал жизненного цикла каждого фрагмента, в
ViewPager
котором есть 4 фрагмента иoffscreenPageLimit = 1 (default value)
FragmentStatePagerAdapter
Перейти к Fragment1 (запуск деятельности)
Перейти к фрагменту 2
Перейти к фрагменту 3
Перейти к фрагменту 4
FragmentPagerAdapter
Перейти к Fragment1 (запуск деятельности)
Перейти к фрагменту 2
Перейти к фрагменту 3
Перейти к фрагменту 4
Вывод :
FragmentStatePagerAdapter
звоните,onDestroy
когда фрагмент преодолен,offscreenPageLimit
аFragmentPagerAdapter
нет.Примечание : я думаю, что мы должны использовать
FragmentStatePagerAdapter
дляViewPager
которых много страниц, потому что это будет хорошо для производительности.Пример из
offscreenPageLimit
:Если мы идем в Fragment3, он будет detroy Fragment1 (или Fragment5 если есть) , потому что
offscreenPageLimit = 1
. Если мы установимoffscreenPageLimit > 1
это, это не разрушит.Если в этом примере мы установим
offscreenPageLimit=4
, нет никакой разницы между использованиемFragmentStatePagerAdapter
илиFragmentPagerAdapter
тем, что Fragment никогда не вызываетonDestroyView
иonDestroy
когда мы меняем вкладкуGithub демо здесь
источник
Что-то, что явно не сказано в документации или в ответах на этой странице (даже если подразумевается @Naruto), это то,
FragmentPagerAdapter
что не будет обновлять фрагменты, если данные в фрагменте изменяются, потому что он сохраняет фрагмент в памяти.Поэтому, даже если у вас есть ограниченное количество отображаемых фрагментов, если вы хотите иметь возможность обновить свои фрагменты (например, повторно запустите запрос для обновления listView во фрагменте), вам необходимо использовать FragmentStatePagerAdapter.
Весь мой смысл здесь в том, что количество фрагментов и то, являются ли они похожими, не всегда является ключевым аспектом для рассмотрения. Являются ли ваши фрагменты динамичными, также имеет ключевое значение.
источник
FragmentPagerAdapter
в своей деятельности, которая использует ViewPager, чтобы показать два фрагмента - где каждый фрагмент содержит список. Мой первый список называется «Все отчеты», а второй - «Избранные отчеты». В первом списке, если я коснусь значка звезды для отчета, он обновит базу данных, чтобы изменить статус избранного этого отчета. Затем я пролистываю и успешно вижу этот отчет в пользовательском интерфейсе второго списка. Так что, возможно, экземпляры хранятся в памяти, но в некоторых случаях (например, у меня) содержимое будет обновляться нормально для FragmentPagerAdapterFragmentPagerAdapter
сохраняет предыдущие данные, извлеченные из адаптера, в то время какFragmentStatePagerAdapter
получает новое значение из адаптера при каждом его выполнении.источник
FragmentStatePagerAdapter = Для размещения большого количества фрагментов в ViewPager. Поскольку этот адаптер уничтожает фрагмент, когда он не виден пользователю, и только сохраненный фрагмент объекта сохраняется для дальнейшего использования. Таким образом используется небольшой объем памяти и достигается лучшая производительность в случае динамических фрагментов.
источник
FragmentPagerAdapter : фрагмент каждой страницы, которую пользователь посещает, будет сохранен в памяти, хотя представление будет уничтожено. Поэтому, когда страница снова станет видимой, представление будет воссоздано, но экземпляр фрагмента не будет воссоздан. Это может привести к значительному использованию памяти. FragmentPagerAdapter следует использовать, когда нам нужно сохранить весь фрагмент в памяти. FragmentPagerAdapter вызывает метод detach (Fragment) вместо транзакции (Fragment).
FragmentStatePagerAdapter : экземпляр фрагмента уничтожается, когда он невидим для пользователя, за исключением сохраненного состояния фрагмента. Это приводит к использованию только небольшого объема памяти и может быть полезно для обработки больших наборов данных. Должен использоваться, когда нам нужно использовать динамические фрагменты, такие как фрагменты с виджетами, поскольку их данные могут храниться в saveInstanceState. Также это не повлияет на производительность, даже если имеется большое количество фрагментов.
источник