tutorial trabajar studio new implement how fragments fragmentos create con android android-fragments android-viewpager android-fragmentactivity

trabajar - Gestión del ciclo de vida de Android de fragmentos dentro de ViewPager y FragmentPagerAdapter



java android fragment (3)

He estado luchando por descubrir cuál es el manejo correcto de los Fragmentos dentro de una FragmentActivity con un ViewPager . Antes de entrar en detalles, un resumen rápido del problema que estoy enfrentando es el siguiente:

Tengo una FragmentActivity con un ViewPager . El ViewPager usa un FragmentPagerAdapter personalizado, pero muy simple. Cada Fragment dentro de ViewPager compone de una ExpandableListView . También tengo un botón de la barra de acción llamado "Refrescar". Por ahora, supongamos que ViewPager tiene solo un Fragment . Se crea la actividad y se Fragment la ExpandableListView del Fragment (hasta ahora todo bien). Cuando se hace clic en el botón Actualizar, el método de manejo dentro de FragmentActivity itera sobre la lista de Fragments que están asignados a FragmentPagerAdapter y llama a refresh() en cada Fragment para poblar su ListView. Sin embargo, cuando la orientación del dispositivo cambia (por ejemplo, de vertical a horizontal), la actividad se recrea y también lo son los fragmentos. Al hacer clic en el botón Actualizar ahora se iterará sobre los Fragments no inicializados.

Sé que estoy siendo bastante vago, especialmente sin código de muestra, pero por favor tengan paciencia conmigo. He rastreado las llamadas al problema y al método de la siguiente manera desde el inicio de la aplicación / actividad:

  1. FragmentActivity.onCreate()
  2. FragmentActivity.setContentView()
  3. FragmentActivity.createPagerFragments() <- esto crea una ArrayList de Fragments y los asigna a un nuevo FragmentPagerAdapter que a su vez está asignado a ViewPager.
  4. Fragment.onAttach()
  5. Fragment.onCreate() <- nada especial aquí, simplemente llamando al súper método.
  6. Fragment.onCreateView() <- nada especial aquí tampoco, solo inflando el diseño
  7. Fragment.onActivityCreated() <- nada aquí tampoco.
  8. << Todo bien, la orientación cambia aquí >>
  9. FragmentActivity.onCreate()
  10. Fragment.onAttach()
  11. Fragment.onCreate()
  12. FragmentActivity.setContentView()
  13. FragmentActivity.createPagerFragments()
  14. Fragment.onCreateView()
  15. Fragment.onActivityCreated()
  16. << Botón Actualizar pulsado >>
  17. FragmentActivity.refresh() <- itera sobre los Fragmentos recién creados desde el # 13 (¡no estos por Android!).
  18. << Crash: NullPointerException para mExpandableListView en Fragment. >>

Entonces, el problema, como lo veo, es el siguiente: cuando Android vuelve a crear FragmentActivity y sus Views después de un cambio de orientación de pantalla (llamadas # 9-15 anteriores), crea nuevos objetos Fragment con su estado restaurado a lo que el los originales fueron Sin embargo, estos parecen estar completamente gestionados por el FragmentManager , y no por el FragmentPagerAdapter . Por el contrario, cuando FragmentPagerAdapter se vuelve a crear junto con los Fragments en el método onCreate la actividad (consulte la llamada n. ° 13) los Fragments que se asignan al adaptador nunca tienen sus métodos Fragment.onCreate() o Fragment.onCreateView() llamados en todas. Entonces cuando se llama al método refresh () (ver # 17) el método itera sobre estos Fragments que no han sido inicializados. Por lo tanto, cuando intentan llenar el ExpandableListView , la variable de instancia de la vista es NULL . Esto es de esperar ya que la variable de instancia solo se asigna en el método Fragment.onCreateView() que nunca recibe llamadas en estos Fragments .

Así que mi pregunta es: ¿cómo se hace una reutilización adecuada de los Fragments recreados (por Android) después de que la orientación de la pantalla ha cambiado para evitar la creación de nuevos que no se inicialicen? Necesito tener una referencia válida para ellos, con el fin de llamar a su método de actualización () que los rellena según demanda. Idealmente, también deberían asignarse al FragmentPagerAdapter .

Espero haber sido claro al describir el problema, y ​​la razón por la que no proporcioné código de muestra es porque el problema (como se puede ver) no proviene del código en sí, sino de una recreación de Fragmentos bastante incorrecta (seemigly) en lugar de volver a usar. Pero si es necesario, puedo darte un código de muestra, simplemente por este camino sería más claro.

¡Gracias!


¿Qué le parece agregar esto a la etiqueta de actividad en su manifiesto?

android:configChanges="orientation"

o esto para API 13 o superior

android:configChanges="orientation|screenSize"

por lo que no volverá a crear tus fragmentos cuando cambie de orientación.


Es mucho para leer, pero después de leer solo la introducción y la pregunta y tener experiencia con FragmentStatePagerAdapter, que es similar a FragmentPagerAdapter, puedo decirle que:

Después de la rotación, su adaptador AUTOMÁTICAMENTE adjuntará fragmentos viejos. Parece que, aunque se recrea el adaptador de creación de actividades, FragmentManager, que es global y recrea la actividad de conservación de instancias, detectará que el nuevo FragmentStatePagerAdapter se combina con el mismo ViewPager y solicita los mismos Fragmentos y simplemente los recuperará de BackStack de Fragment.

Usted como diseñador de Fragments puede observar este comportamiento al continuar la invocación de Fragment.onAttach () y Fragment.onDetach (). Cuando onAttach () ocurre, o bien se crea su Fragmento o se reutiliza después de la rotación. Debería poder distinguir que Fragment se rotó con el uso de callback onRestoreRnstanceState ().

Verá en sus registros muchos onCreate () y otros registros de estados simultáneamente, porque FragmentStatePagerAdapter siempre busca / crea min 3 Fragments (excepto si establece que solo son 2 o 1), por lo que también después de la rotación de la pantalla se volverán a unir tres fragmentos de pila posterior.

Espero que haya ayudado.


Creo que esta pregunta sobre cómo recuperar el fragmento actual de un ViewPager lo ayudará. Como ya se señaló, los fragmentos son administrados por el Fragment (State) PagerAdapter y NOT Activity o Fragment''s lifecycle.

  • La primera vez que se crea la actividad, el método getItem devuelve los getItem . Este método se llama solo una vez por fragmento, incluso si la actividad se vuelve a crear.
  • Tiempos posteriores, los fragmentos son devueltos por el método instantiateItem . Lo más probable es que este sea el lugar donde necesite obtener sus fragmentos y llamar a sus métodos de actualización.