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

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

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

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

А насчет FragmentStatePagerAdapter:

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

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

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

Итак, мои вопросы: какой адаптер я должен использовать? FragmentPagerAdapter или FragmentStatePagerAdapter?

Ответ 1

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

Ответ 2

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

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

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

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

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

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

Чтобы быть более подробным,

FragmentStatePagerAdapter:

  • с FragmentStatePagerAdapter, ваш ненужный фрагмент destroy.The совершает полное удаление фрагмент из вашей активности FragmentManager.

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

FragmentPagerAdapter:

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

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

Ответ 3

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

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

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

Ответ 4

Вот жизненный цикл журнала каждого фрагмента в 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 которого много страниц, потому что это хорошо для производительности.

Пример offscreenPageLimit:

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

Демо-версия Github

Ответ 5

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

Ответ 6

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

Ответ 7

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

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

Поэтому рекомендуется использовать FragmentPagerAdapter только при наличии небольшого количества фрагментов для ViewPager. Было бы еще лучше, если бы фрагменты были статическими, поскольку у них не было бы большого количества объектов, экземпляры которых будут храниться. Надеюсь, это очистит разницу между Android FragmentPagerAdapter и FragmentStatePagerAdapter. Если вам нравится эта статья, поделитесь ею со своими друзьями в Google+ и Facebook, также как и наша страница на Facebook для получения последних обновлений.