Разница между FragmentPagerAdapter и FragmentStatePagerAdapter

в чем разница между FragmentPagerAdapter и FragmentStatePagerAdapter?

о FragmentPagerAdapter руководство Google говорит:

эта версия пейджера лучше всего использовать, когда есть несколько как правило, больше статических фрагментов для пролистывания, таких как набор вешалки. Фрагмент каждой страницы, которую посетит пользователь, будет сохранен память, хотя ее иерархия представлений может быть уничтожена, когда она невидима. Это может привести к использованию значительного объема памяти, так как фрагмент экземпляры могут сохранять произвольное количество состояний. Для больших наборов из страниц рассмотрим FragmentStatePagerAdapter.

и о FragmentStatePagerAdapter:

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

Итак, у меня есть только 3 фрагмента. Но все они являются отдельными модулями с большим объемом данных.

Fragment1 обрабатывает некоторые данные (которые вводят пользователи) и передает их через activity в Fragment2, что просто ListFragment. Fragment3 тоже ListFragment.

Итак, мои вопросы are: Какой адаптер лучше использовать? FragmentPagerAdapter или FragmentStatePagerAdapter?

6 ответов


как говорят врачи, подумайте об этом таким образом. Если вы должны были сделать приложение, как для чтения книг, вы не захотите загружать все фрагменты в память сразу. Вы хотели бы загрузить и уничтожить Fragments как пользователь читает. В этом случае вы будете использовать FragmentStatePagerAdapter. Если вы просто отображаете 3 "вкладки", которые не содержат много тяжелых данных (например,Bitmaps), то FragmentPagerAdapter возможно, Вам подойдет. Кроме того, имейте в виду, что ViewPager по умолчанию будет загружать 3 фрагмента в память. Первый Adapter вы упомянули, может уничтожить View иерархия и повторно загрузить его, когда это необходимо, второй Adapter сохраняет только состояние Fragment и полностью уничтожает его, если пользователь затем возвращается на эту страницу, состояние извлекается.


  • FragmentPagerAdapter хранит весь фрагмент в памяти, и может увеличьте накладные расходы памяти, если используется большое количество фрагментов ViewPager.

  • в противоположность своему брату,FragmentStatePagerAdapter только в магазинах savedInstanceState фрагментов и уничтожает все фрагменты, когда они теряют концентрацию.

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

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

  • было бы еще лучше, если бы фрагменты были статическими, так как они не иметь большого количества объектов, экземпляры которых были бы на хранении.

более подробно,

FragmentStatePagerAdapter:

  • С FragmentStatePagerAdapter,ваш ненужный фрагмент разрушенный.Транзакция совершается для полного удаления фрагмент из вашей деятельности FragmentManager.

  • государство FragmentStatePagerAdapter исходит из того, что он спасет ваш фрагмент Bundle С savedInstanceState когда она уничтожена.Когда пользователь переходит назад,новый фрагмент будет восстановлено с использованием состояния фрагмента.

FragmentPagerAdapter:

  • по сравнению FragmentPagerAdapter ничего подобного.Когда фрагмент больше не нужен.FragmentPagerAdapter вызовы detach(Fragment) на транзакция вместо remove(Fragment).

  • это разрушает представление фрагмента, но оставляет экземпляр фрагмента живой в FragmentManager.Итак, фрагменты, созданные в FragmentPagerAdapter никогда не уничтожаются.


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

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

вся моя точка зрения здесь в том, что количество фрагментов и то, похожи они или нет, не всегда является ключевым аспектом для рассмотрения. Также важно, являются ли ваши фрагменты динамическими.


вот жизненный цикл журнала каждого фрагмента в ViewPager которые имеют 4 фрагмента и offscreenPageLimit = 1 (default value)

FragmentStatePagerAdapter

перейти к Fragment1 (запуск активности)

Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart

перейти к Fragment2

Fragment3: onCreateView
Fragment3: onStart

перейти к Fragment3

Fragment1: onStop
Fragment1: onDestroyView
Fragment1: onDestroy
Fragment1: onDetach
Fragment4: onCreateView
Fragment4: onStart

перейти к Fragment4

Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy

FragmentPagerAdapter

перейти к Fragment1 (запуск активность)

Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart

перейти к Fragment2

Fragment3: onCreateView
Fragment3: onStart

перейти к Fragment3

Fragment1: onStop
Fragment1: onDestroyView
Fragment4: onCreateView
Fragment4: onStart

перейти к Fragment4

Fragment2: onStop
Fragment2: onDestroyView

вывод: FragmentStatePagerAdapter вызов onDestroy когда фрагмент преодолен offscreenPageLimit пока FragmentPagerAdapter нет.

Примечание: я думаю, мы должны использовать FragmentStatePagerAdapter на ViewPager, которые имеют много страниц, потому что это будет хорошо для производительности.

пример of offscreenPageLimit:

если мы пойдем в Fragment3, это будет detroy Fragment1 (или Fragment5, если есть), потому что offscreenPageLimit = 1. Если мы установим offscreenPageLimit > 1 это не будет уничтожить.
Если в этом примере мы задаем offscreenPageLimit=4, нет разницы между использованием FragmentStatePagerAdapter или FragmentPagerAdapter потому что фрагмент никогда не звонит onDestroyView и onDestroy когда мы меняем вкладке

гитхаб демо здесь


FragmentPagerAdapter хранит предыдущие данные, которые извлекаются из адаптера в то время как FragmentStatePagerAdapter принимает новое значение от адаптера каждый раз, когда он выполняется.


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