android - inside - Navegando de regreso a FragmentPagerAdapter-> los fragmentos están vacíos
fragmentpageradapter example (4)
Acabo de enfrentar el problema en nuestro proyecto también. La causa principal es la forma en que funciona el FragmentPagerAdapter:
El FragmentPagerAdapter simplemente separa un Fragmento que actualmente no necesita de su Vista, pero no lo elimina de su FragmentManager. Cuando quiera volver a mostrar el Fragmento, observa si el FragmentManager aún contiene el Fragmento utilizando una etiqueta creada a partir de la ID de la vista de ViewPager y la ID devuelta por la llamada a los adaptadores getItemId (posición). Si encuentra un Fragmento, simplemente programa un anexo del Fragmento a su Vista dentro de la transacción de actualización de FragmentManager. Solo si no encuentra un Fragmento de esta manera, crea uno nuevo usando la llamada getItem (position) de los adaptadores.
El problema con un Fragmento que contiene una ViewPager con un FragmentPagerAdapter es que el contenido de FragmentManager nunca se limpia cuando el Fragment que lo contiene se pone en la pila posterior. Si el Fragmento que lo contiene vuelve de la pila posterior, crea una nueva Vista, pero el Administrador de Fragmentos aún contiene los fragmentos que se adjuntaron a la vista anterior y la conexión de un fragmento existente ya no funciona.
La forma más fácil de deshacerse de este problema es evitar fragmentos anidados. :)
La segunda manera más fácil es, como ya se mencionó en otras publicaciones, utilizar el ChildFragmentManager para FragmentPagerAdapter, ya que este se actualiza correctamente durante el ciclo de vida del fragmento de contenedor.
Como hay proyectos (como mi actual) donde ambas opciones no son posibles, he publicado aquí una solución que funciona con un FragmentManager arbitrario usando el hashCode de los subfragmentos como el id del ítem del fragmento en esa posición. Viene al precio de almacenar todos los fragmentos para todas las posiciones dentro del adaptador.
public class MyPagerAdapter extends FragmentPagerAdapter {
private static int COUNT = ...;
private final FragmentManager fragmentManager;
private Fragment[] subFragments = new Fragment[COUNT];
private FragmentTransaction cleanupTransaction;
public MyPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
this.fragmentManager = fragmentManager;
}
@Override
public Fragment getItem(int position) {
return getSubFragmentAtPosition(position);
}
@Override
public int getCount() {
return COUNT;
}
@Override
public long getItemId(int position) {
return getSubFragmentAtPosition(position).hashCode();
}
//The next three methods are needed to remove fragments no longer used from the fragment manager
@Override
public void startUpdate(ViewGroup container) {
super.startUpdate(container);
cleanupTransaction = fragmentManager.beginTransaction();
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
cleanupTransaction.remove((Fragment) object);
}
@Override
public void finishUpdate(ViewGroup container) {
super.finishUpdate(container);
cleanupTransaction.commit();
}
private Fragment getSubFragmentAtPosition(int position){
if (subFragments[position] == null){
subFragments[position] = ...;
}
return subFragments[position];
}
}
Tengo un Fragmento (lo llamaré pagerFragment
) que se agrega a la backstack y está visible. Tiene una viewPager
con un FragmentPagerAdapter
. El FragmentPagerAdapter
contiene (digamos) dos fragmentos: A y B.
La primera adición de los fragmentos funciona muy bien.
El fragmento A tiene un botón que, una vez que se presiona, agrega un fragmento (C) a la pila posterior.
El problema es este: si agrego ese fragmento (C) y luego pagerAdapter
clic en Atrás, el pagerAdapter
está vacío y no puedo ver ningún fragmento dentro.
Si utilizo un hack y destruyo los fragmentos pagerFragment
(A y B) en el pagerFragment
onDestroyView()
, esto resuelve el problema, aunque no quiero usar este hack.
¿Alguna idea de lo que podría ser el problema?
Parece que está utilizando fragmentos anidados dado que su ViewPager está dentro de un fragmento de paginación. ¿Has pasado getChildFragmentManager () al constructor de tu FragmentPagerAdapter? Si no, deberías.
No creo que necesites un FragmentStatePagerAdapter, pero daría una oportunidad, ya que maneja el guardado y la restauración del estado de Fragment. El hecho de que tu truco onDestroyView () funcione me hace pensar que es posible que desees un FragmentStatePagerAdapter.
También podría tener algo que ver con la forma en que FragmentPagerAdapter agrega Fragments. El FragmentPagerAdapter no agrega Fragmentos a la backstack. Imagínese si tuviera más de 10 páginas agregadas en su ViewPager y el usuario pasara a través de ellas. El usuario tendría que devolver el golpe 11 veces solo para salir de la aplicación.
También puede estar relacionado con esta publicación: Fragmentos anidados y Back Stack .
Además, no estoy seguro de a qué está agregando el Fragmento C. ¿Lo está agregando al mismo contenedor que ViewPager?
Bueno, al menos tienes algunas opciones para investigar. En estas situaciones, me gusta depurar en el código fuente de Android SDK y ver qué está causando el comportamiento. Recomiendo aprovechar la fuente AOSP y agregar frameworks / soporte y frameworks / base como fuentes de SDK. Esa es la única forma verdadera de entender lo que está sucediendo y evitar hacer cambios aleatorios hasta que las cosas funcionen.
Utilice getChildFragmentManager()
lugar de getSupportFragmentManager()
. Funcionará bien.
Yo tuve el mismo problema. La solución para mí fue simple:
en onCreateView tuve:
// Create the adapter that will return a fragment for each of the three
// primary sections of the app.
mSectionsPagerAdapter = new SectionsPagerAdapter(getActivity()
.getSupportFragmentManager());
donde SectionPageAdapter es algo como esto:
class SectionsPagerAdapter extends FragmentPagerAdapter {
...
}
después de cambiar getSupportFragmentManager a
mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
¡comenzó a funcionar! Espero que esto ayude.