android - ondestroyview - Diferencia entre FragmentPagerAdapter y FragmentStatePagerAdapter
fragmentstatepageradapter vs fragmentpageradapter (6)
¿Cuál es la diferencia entre FragmentPagerAdapter
y FragmentStatePagerAdapter
?
Acerca de FragmentPagerAdapter
La guía de Google dice:
Esta versión del buscapersonas es mejor para usar cuando hay un puñado de fragmentos típicamente estáticos, como un conjunto de pestañas. El fragmento de cada página que visiten los usuarios se guardará en la memoria, aunque su jerarquía de vistas puede destruirse cuando no esté visible. Esto puede resultar en el uso de una cantidad significativa de memoria, ya que las instancias de fragmentos pueden conservar una cantidad arbitraria de estado. Para conjuntos de páginas más grandes, considere FragmentStatePagerAdapter.
Y sobre FragmentStatePagerAdapter
:
Esta versión del buscapersonas es más útil cuando hay una gran cantidad de páginas, que funcionan más como una vista de lista. Cuando las páginas no son visibles para el usuario, su fragmento completo puede ser destruido, solo manteniendo el estado guardado de ese fragmento. Esto permite que el buscapersonas retenga mucha menos memoria asociada con cada página visitada en comparación con FragmentPagerAdapter, lo que podría generar una sobrecarga mayor al cambiar de página.
Así que solo tengo 3 fragmentos. Pero todos ellos son módulos separados con una gran cantidad de datos.
Fragment1
maneja algunos datos (que ingresan los usuarios) y los pasa a través de la actividad a Fragment2
, que es solo un simple ListFragment
. Fragment3
también es un ListFragment
.
Así que mis preguntas son : ¿Qué adaptador debo usar? FragmentPagerAdapter
o FragmentStatePagerAdapter
?
Algo que no se dice explícitamente en la documentación o en las respuestas en esta página (aunque implícito en @Naruto), es que FragmentPagerAdapter
no 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, vuelva a ejecutar la consulta para actualizar el listView en el Fragmento), necesita usar FragmentStatePagerAdapter.
Mi punto aquí es que el número de Fragmentos y si son o no similares no siempre es el aspecto clave a considerar. Si tus fragmentos son dinámicos también es clave.
Aquí hay un ciclo de vida de registro de cada fragmento en ViewPager
que tiene 4 fragmentos y offscreenPageLimit = 1 (default value)
FragmentStatePagerAdapter
Ir a Fragment1 (actividad de lanzamiento)
Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart
Ir a Fragment2
Fragment3: onCreateView
Fragment3: onStart
Ir a Fragment3
Fragment1: onStop
Fragment1: onDestroyView
Fragment1: onDestroy
Fragment1: onDetach
Fragment4: onCreateView
Fragment4: onStart
Ir a Fragment4
Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy
FragmentPagerAdapter
Ir a Fragment1 (actividad de lanzamiento)
Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart
Ir a Fragment2
Fragment3: onCreateView
Fragment3: onStart
Ir a Fragment3
Fragment1: onStop
Fragment1: onDestroyView
Fragment4: onCreateView
Fragment4: onStart
Ir a Fragment4
Fragment2: onStop
Fragment2: onDestroyView
Conclusión : FragmentStatePagerAdapter
llama onDestroy
cuando se supera el Fragmento offscreenPageLimit
onDestroy
mientras que FragmentPagerAdapter
no.
Nota : creo que deberíamos usar FragmentStatePagerAdapter
para un ViewPager
que tiene mucha página porque será bueno para el rendimiento.
Ejemplo de offscreenPageLimit
:
Si vamos a Fragment3, destruirá Fragmento 1 (o Fragmento 5 si tiene) porque offscreenPageLimit = 1
. Si configuramos offscreenPageLimit > 1
no se destruirá.
Si en este ejemplo, configuramos offscreenPageLimit=4
, no hay ninguna diferencia entre usar FragmentStatePagerAdapter
o FragmentPagerAdapter
porque Fragment nunca llama onDestroyView
y onDestroy
cuando cambiamos la pestaña
Como dicen los doctores, piénsalo 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. Le gustaría cargar y destruir Fragments
medida que el usuario lee. En este caso utilizará FragmentStatePagerAdapter
. Si solo está mostrando 3 "pestañas" que no contienen una gran cantidad de datos pesados (como Bitmaps
), FragmentPagerAdapter
podría serle de utilidad. Además, tenga en cuenta que ViewPager
por defecto cargará 3 fragmentos en la memoria. El primer Adapter
que mencione podría destruir la jerarquía de View
y volver a cargarlo cuando sea necesario, el segundo Adapter
solo guarda el estado del Fragment
y lo destruye completamente, si el usuario vuelve a esa página, se recupera el estado.
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 estado de fragmento guardado del fragmento para su uso posterior. De esta manera, se utiliza una cantidad baja de memoria y se entrega un mejor rendimiento en caso de fragmentos dinámicos.
FragmentPagerAdapter
almacena los datos anteriores que se obtienen del adaptador, mientras que FragmentStatePagerAdapter
toma el nuevo valor del adaptador cada vez que se ejecuta.
FragmentPagerAdapter
almacena todo el fragmento en la memoria, y podría aumentar la sobrecarga de memoria si se utiliza una gran cantidad de fragmentos enViewPager
.Al contrario que su hermano,
FragmentStatePagerAdapter
solo almacena el estado de la instancia guardada de los fragmentos, y destruye todos los fragmentos cuando pierden el enfoque.Por lo tanto,
FragmentStatePagerAdapter
debe usarse cuando tenemos que usar fragmentos dinámicos, como fragmentos con widgets, ya que sus datos podrían almacenarse en el estado desavedInstanceState
guardado.savedInstanceState
afectará el rendimiento incluso si hay una gran cantidad de fragmentos.Por el contrario, su hermano
FragmentPagerAdapter
debe usarse cuando necesitamos almacenar todo el fragmento en la memoria.Cuando digo que todo el fragmento se guarda en la memoria, significa que sus instancias no serán destruidas y crearían una sobrecarga de memoria. Por lo tanto, se recomienda usar
FragmentPagerAdapter
solo cuando hay un número bajo de fragmentos paraViewPager
.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 mas detallista,
FragmentStatePagerAdapter:
con
FragmentStatePagerAdapter
, su fragmento innecesario se destruye. Se compromete una transacción para eliminar completamente el fragmento del FragmentManager de su actividad.El estado en
FragmentStatePagerAdapter
proviene del hecho de que guardará elBundle
de su fragmento desavedInstanceState
cuando sesavedInstanceState
Cuando el usuario navega hacia atrás, el nuevo fragmento se restaurará usando el estado del fragmento.
FragmentPagerAdapter:
Por comparación,
FragmentPagerAdapter
no hace nada de ese tipo. Cuando el fragmento ya no es necesario.FragmentPagerAdapter
llama adetach(Fragment)
en la transacción en lugar deremove(Fragment)
.Esta destrucción es la vista del fragmento, pero deja la instancia del fragmento viva en el
FragmentManager
los fragmentos creados en elFragmentPagerAdapter
nunca se destruyen.