¿Cuál es la diferencia entre FragmentPagerAdapter y FragmentStatePagerAdapter?

375

¿Cuál es la diferencia entre FragmentPagerAdaptery FragmentStatePagerAdapter?

Sobre FragmentPagerAdapterla guía de Google dice:

Esta versión del buscapersonas es mejor para usar cuando hay un puñado de fragmentos típicamente más estáticos para ser buscados, como un conjunto de pestañas. El fragmento de cada página que visita el usuario se mantendrá en la memoria, aunque su jerarquía de visualización puede destruirse cuando no sea visible. Esto puede resultar en el uso de una cantidad significativa de memoria ya que las instancias de fragmentos pueden retener una cantidad arbitraria de estado. Para conjuntos de páginas más grandes, considere FragmentStatePagerAdapter.

Y sobre FragmentStatePagerAdapter:

Esta versión del localizador es más útil cuando hay una gran cantidad de páginas, ya que funciona más como una vista de lista. Cuando las páginas no son visibles para el usuario, su fragmento completo puede destruirse, solo manteniendo el estado guardado de ese fragmento. Esto permite que el localizador conserve mucha menos memoria asociada con cada página visitada en comparación con FragmentPagerAdapterel costo de una sobrecarga potencial al cambiar de página.

Entonces solo tengo 3 fragmentos. Pero todos ellos son módulos separados con una gran cantidad de datos.

Fragment1maneja algunos datos (que ingresan los usuarios) y los pasa a través de la actividad Fragment2, lo cual es simple ListFragment. Fragment3también es a ListFragment.

Entonces mis preguntas son : ¿Qué adaptador debo usar? FragmentPagerAdaptero FragmentStatePagerAdapter?

AlexMomotov
fuente
2
Creo que tener solo 3 Fragmentos lo califica para usar FragmentPagerAdapter. Las pestañas para estos Fragmentos probablemente serán visibles simultáneamente.
IgorGanapolsky
2
este post guarda mis 5-6 horas porque el uso de un tipo incorrecto de adaptador
Nantaphop
1
La respuesta a esta pregunta arroja una pregunta más stackoverflow.com/questions/9156406/…
Piyush Kukadiya
existe FragmentPagerAdaptery FragmentStatePagerAdapterpero lo que es FragmentStateAdapter?
the_prole

Respuestas:

292

Como dicen los documentos, piénselo de esta manera. Si tuviera que hacer una aplicación como un lector de libros, no querrá cargar todos los fragmentos en la memoria a la vez. Desea cargar y destruir Fragmentsmientras el usuario lee. En este caso lo usarás FragmentStatePagerAdapter. Si solo está mostrando 3 "pestañas" que no contienen muchos datos pesados ​​(como Bitmaps), entonces FragmentPagerAdapterpodría ser adecuado para usted. Además, tenga en cuenta que, ViewPagerde forma predeterminada, cargará 3 fragmentos en la memoria. Lo primero Adapterque menciona puede destruir la Viewjerarquía y volver a cargarla cuando sea necesario, la segunda Adaptersolo guarda el estado de la Fragmenty la destruye por completo, si el usuario vuelve a esa página, se recupera el estado.

Emmanuel
fuente
Tengo varios botones y vistas de texto en Fragment1 y ListView que generan elementos dinámicamente en Fragment2 y Fragment3. ¿Crees que es una buena idea usar FragmentStatePagerAdapter y almacenar todos los datos en Activity, pasándolos a Fragments a través de Bundle?
AlexMomotov
2
@AlexMomotov Las vistas en el diseño del Fragment no tienen nada que ver con la elección de FragmentStatePagerAdapter. La pregunta aquí es la cantidad de Fragmentos que serán buscados.
IgorGanapolsky
1
Básicamente, no hay nada a favor de FragmentPagerAdapterusarlo.
Tomasz Mularczyk
3
La ventaja de @Tomasz FragmentPagerAdapteres que cambiar entre fragmentos podría ser mucho más rápido, ya que los Fragmentobjetos reales no necesitan ser reconstruidos cada vez. Por otro lado, esto terminaría usando más memoria que contiene los objetos de fragmento en memoria.
Richard Le Mesurier
Tengo 3 pestañas / páginas (cada una de las cuales muestra un WebView), así que he usado FragmentPagerAdapter . Sin embargo, la última página todavía se vuelve a dibujar cuando la deslizo desde la primera página. Para resolver esto, he usado viewPager.setOffscreenPageLimit(2).
prohibición de geoingeniería
131
  • FragmentPagerAdapteralmacena todo el fragmento en la memoria y podría aumentar la sobrecarga de la memoria si se usa una gran cantidad de fragmentos ViewPager.

  • Por el contrario, su hermano FragmentStatePagerAdaptersolo almacena el estado guardado de fragmentos y destruye todos los fragmentos cuando pierden el foco.

  • Por FragmentStatePagerAdapterlo tanto, debe usarse cuando tengamos que usar fragmentos dinámicos, como fragmentos con widgets, ya que sus datos podrían almacenarse en el savedInstanceStatearchivo. También no afectará el rendimiento incluso si hay una gran cantidad de fragmentos.

  • Por el contrario, su hermano FragmentPagerAdapterdebe usarse cuando necesitemos almacenar todo el fragmento en la memoria.

  • Cuando digo que todo el fragmento se guarda en la memoria, significa que sus instancias no se destruirán y crearían una sobrecarga de memoria. Por lo tanto, se recomienda usar FragmentPagerAdaptersolo cuando haya un número bajo de fragmentos ViewPager.

  • Sería aún mejor si los fragmentos son estáticos, ya que no tendrían una gran cantidad de objetos cuyas instancias se almacenarían.

Para ser más detallados,

FragmentStatePagerAdapter:

  • con FragmentStatePagerAdapter, su fragmento innecesario se destruye. Una transacción se compromete a eliminar completamente el fragmento de su actividad FragmentManager.

  • El estado FragmentStatePagerAdapterviene del hecho de que guardará el fragmento Bundlede savedInstanceStatecuando se destruye. Cuando el usuario navega hacia atrás, el nuevo fragmento se restaurará utilizando el estado del fragmento.

FragmentPagerAdapter:

  • Por comparación FragmentPagerAdapterno se hace nada por el estilo. Cuando el fragmento ya no es necesario. FragmentPagerAdapterllama detach(Fragment)a la transacción en lugar de remove(Fragment).

  • Esto destruye la vista del fragmento pero deja viva la instancia del fragmento en el FragmentManager.so los fragmentos creados en el FragmentPagerAdapternunca se destruyen.

Steve
fuente
2
¿Por qué tienes 2 respuestas?
Jared Burrows
¿Cuál es el beneficio de mantener fragmentos enteros en la memoria?
Tomasz Mularczyk
44
@Tomek: si el siguiente fragmento ya está instanciado (es decir, FragmentPagerAdapter), estará listo para renderizarse cuando lo deslices, por lo que la animación de deslizamiento será más suave. Con FragmentStatePagerAdapter, la siguiente instancia de fragmento puede no existir hasta que se deslice hacia ella, y si es un fragmento grande que es costoso de crear, puede ver un tartamudeo en la animación. Es una cuestión de rendimiento versus consumo de memoria.
Dalbergia
1
@Jared Burrows porque uno es solo AnswerText que es bueno para respuestas pequeñas y estáticas y el otro es AnswerStateText que es para respuestas más grandes y dinámicas
Simple Fellow
48

Aquí hay un ciclo de vida de registro de cada fragmento en el ViewPagerque hay 4 fragmentos yoffscreenPageLimit = 1 (default value)

FragmentStatePagerAdapter

Ir al Fragmento1 (actividad de lanzamiento)

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

Ir al fragmento 2

Fragment3: onCreateView
Fragment3: onStart

Ir al fragmento 3

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

Ir al fragmento 4

Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy

FragmentPagerAdapter

Ir al Fragmento1 (actividad de lanzamiento)

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

Ir al fragmento 2

Fragment3: onCreateView
Fragment3: onStart

Ir al fragmento 3

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

Ir al fragmento 4

Fragment2: onStop
Fragment2: onDestroyView

Conclusión : FragmentStatePagerAdapterllame onDestroycuando se supere el Fragmento offscreenPageLimitmientras FragmentPagerAdapterno.

Nota : Creo que deberíamos usar FragmentStatePagerAdapteruna ViewPagerque tenga mucha página porque será buena para el rendimiento.

Ejemplo de offscreenPageLimit:

Si vamos a Fragment3, que se Detroy Fragment1 (o si tenga Fragment5) debido offscreenPageLimit = 1. Si establecemos offscreenPageLimit > 1que no va a destruir.
Si en este ejemplo, establecemos offscreenPageLimit=4, no hay diferencia entre usar FragmentStatePagerAdaptero FragmentPagerAdapterporque Fragment nunca llama onDestroyViewy onDestroycuando cambiamos la pestaña

Demostración de Github aquí

Phan Van Linh
fuente
¡Qué gran forma de conclusión!
Rahul Rastogi
buena explicación
gourav singhal
1
Buena explicación Dijiste que usar FragmentStatePagerAdapter cuando tienes muchas páginas es bueno para el rendimiento. ¿Quiso decir que es bueno para ahorrar memoria? El objetivo, según tengo entendido, es preservar la memoria en caso de posibles muchas instancias de Fragment, por lo que el rendimiento es el beneficio implícito; el objetivo explícito es preservar la memoria
Hatzil
38

Algo que no se dice explícitamente en la documentación o en las respuestas en esta página (aunque implícito por @Naruto), es que FragmentPagerAdapterno actualizará los Fragmentos si los datos en el Fragmento cambian porque mantiene el Fragmento en la memoria.

Entonces, incluso si tiene un número limitado de Fragmentos para mostrar, si desea poder actualizar sus fragmentos (por ejemplo, si vuelve a ejecutar la consulta para actualizar listView en el Fragmento), debe usar FragmentStatePagerAdapter.

Mi punto principal aquí es que la cantidad de Fragmentos y si son similares o no no siempre es el aspecto clave a considerar. Si sus fragmentos son dinámicos o no también es clave.

JDenais
fuente
Digamos que tengo 2 fragmentos, 1 vista de reciclador en el fragmento A, cuando hago clic en un elemento que cambia el contenido del fragmento B, digamos que hago fragB.setText ("blablabla"). ¿Debo usar la página de estado entonces?
Ced
No estoy seguro pero diría que sí. Simplemente pruebe ambos, de todos modos es muy fácil y rápido cambiar su código de uno a otro.
JDenais
@JDenais ¿Estás seguro de que esto es correcto? Estoy usando FragmentPagerAdapteren mi actividad que usa un ViewPager para mostrar dos fragmentos, donde cada fragmento contiene una lista. Mi primera lista se llama "Todos los informes" y la segunda lista es "Informes favoritos". En la primera lista, si toco el icono de estrella para un informe, actualiza la base de datos para alternar el estado favorito de ese informe. Luego deslizo y veo con éxito este informe en la interfaz de usuario de la segunda lista. Así que tal vez los casos se mantienen en la memoria, pero en algunos casos (por ejemplo, la mía) el contenido en realidad se actualizará bien para FragmentPagerAdapter
suspensión de la geoingeniería
14

FragmentPagerAdapteralmacena los datos anteriores que se obtienen del adaptador mientras FragmentStatePagerAdaptertoma el nuevo valor del adaptador cada vez que se ejecuta.

vinay kumar
fuente
4

FragmentStatePagerAdapter = Para acomodar una gran cantidad de fragmentos en ViewPager. Como este adaptador destruye el fragmento cuando no es visible para el usuario y solo se guarda el estadoInstanceState del fragmento para su uso posterior. De esta forma, se utiliza una pequeña cantidad de memoria y se entrega un mejor rendimiento en caso de fragmentos dinámicos.

Dwivedi Ji
fuente
1

FragmentPagerAdapter : el fragmento de cada página que visita el usuario se almacenará en la memoria, aunque se destruirá la vista. Por lo tanto, cuando la página vuelva a estar visible, la vista se volverá a crear pero la instancia del fragmento no se volverá a crear. Esto puede ocasionar que se use una cantidad significativa de memoria. FragmentPagerAdapter debe usarse cuando necesitamos almacenar todo el fragmento en la memoria. FragmentPagerAdapter llama a detach (Fragment) en la transacción en lugar de eliminar (Fragment).

FragmentStatePagerAdapter : la instancia del fragmento se destruye cuando no es visible para el usuario, excepto el estado guardado del fragmento. Esto resulta en el uso de solo una pequeña cantidad de memoria y puede ser útil para manejar conjuntos de datos más grandes. Debería usarse cuando tengamos que usar fragmentos dinámicos, como fragmentos con widgets, ya que sus datos podrían almacenarse en el estado guardado de la entrada. Tampoco afectará el rendimiento incluso si hay una gran cantidad de fragmentos.

foroogh.Varmazyar
fuente