¿Es esta la manera correcta de limpiar el Fragmento de la stack trasera al dejar una stack profundamente anidada?

Estoy usando la biblioteca de compatibilidad de Android para implementar fragmentos y he extendido la muestra de diseño para que un fragmento contenga un botón que dispare otro fragmento.

En el panel de selección de la izquierda, tengo 5 elementos seleccionables: ABCDE .

Cada uno carga un fragmento (a través de FragmentTransaction:replace ) en el panel de detalles – abcde

Ahora he extendido el fragmento e para que contenga un botón que carga otro fragmento e1 también en el panel de detalles. He hecho esto en el método onClick de fragment e de la siguiente manera:

 FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction(); ft.replace(R.id.details_frag, newFrag); ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); ft.addToBackStack(null); ft.commit(); 

Si hago las siguientes selecciones:

 E - e - e1 - D - E 

Entonces el fragmento e está en el panel de detalles. Esto está bien y lo que quiero. Sin embargo, si presiono el botón back en este punto, no hace nada. Tengo que hacer clic dos veces porque e1 todavía está en la stack. Además, después de hacer clic, obtuve una excepción de puntero nulo en onCreateView:

Para ‘resolver’ este problema, agregué lo siguiente siempre que se selecciona ABCDE :

 FragmentManager fm = getActivity().getSupportFragmentManager(); for(int i = 0; i < fm.getBackStackEntryCount(); ++i) { fm.popBackStack(); } 

Me pregunto si esta es la solución correcta o si debería estar haciendo algo diferente.

Bueno, hay algunas maneras de hacerlo, dependiendo del comportamiento previsto, pero este enlace debe ofrecerle todas las mejores soluciones y no es sorprendente que sea de Dianne Hackborn.

http://groups.google.com/group/android-developers/browse_thread/thread/d2a5c203dad6ec42

Esencialmente tienes las siguientes opciones

  • Use un nombre para su estado inicial de stack posterior y use FragmentManager.popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE) .
  • Utilice FragmentManager.getBackStackEntryCount() / getBackStackEntryAt().getId() para recuperar el ID de la primera entrada en la stack posterior, y FragmentManager.popBackStack(int id, FragmentManager.POP_BACK_STACK_INCLUSIVE) .
  • FragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE) supone que FragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE) extrae toda la stack posterior … Creo que la documentación es incorrecta. (En realidad, supongo que simplemente no cubre el caso en el que pasa en POP_BACK_STACK_INCLUSIVE ),

La otra solución limpia si no desea mostrar todas las entradas de la stack …

 getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); getSupportFragmentManager().beginTransaction().replace(R.id.home_activity_container, fragmentInstance).addToBackStack(null).commit(); 

Esto limpiará la stack primero y luego cargará un nuevo fragmento, por lo que en cualquier punto dado tendrás solo un único fragmento en la stack

Gracias a la respuesta de Joachim , uso el código para borrar finalmente la entrada de la stack trasera.

 // In your FragmentActivity use getSupprotFragmentManager() to get the FragmentManager. // Clear all back stack. int backStackCount = getSupportFragmentManager().getBackStackEntryCount(); for (int i = 0; i < backStackCount; i++) { // Get the back stack fragment id. int backStackId = getSupportFragmentManager().getBackStackEntryAt(i).getId(); fm.popBackStack(backStackId, FragmentManager.POP_BACK_STACK_INCLUSIVE); } /* end of for */ 

He investigado mucho para limpiar Backstack, y finalmente veo Transaction BackStack y su administración . Aquí está la solución que mejor funcionó para mí.

  // CLEAR BACK STACK. private void clearBackStack() { final FragmentManager fragmentManager = getSupportFragmentManager(); while (fragmentManager.getBackStackEntryCount() != 0) { fragmentManager.popBackStackImmediate(); } } 

El método anterior recorre todas las transacciones en la stack de respaldo y las elimina inmediatamente de a una por vez.

Nota: el código anterior algunas veces no funciona y me enfrento a ANR debido a este código, así que por favor no intente esto.

El método de actualización a continuación elimina todos los registros de ese “nombre” de backstack.

 FragmentManager fragmentManager = getSupportFragmentManager(); fragmentManager.popBackStack("name",FragmentManager.POP_BACK_STACK_INCLUSIVE); 
  • nombre Si no es nulo, este es el nombre de un estado anterior a buscar; si se encuentra, todos los estados hasta ese estado serán reventados. los
  • El indicador POP_BACK_STACK_INCLUSIVE se puede usar para controlar si el estado nombrado se ha reventado. Si es nulo, solo aparece el estado superior.

Estoy usando un código similar al que usa el ciclo while, pero llamo el conteo de entrada en cada ciclo … así que supongo que es algo más lento

 FragmentManager manager = getFragmentManager(); while (manager.getBackStackEntryCount() > 0){ manager.popBackStackImmediate(); } 
  // pop back stack all the way final FragmentManager fm = getSherlockActivity().getSupportFragmentManager(); int entryCount = fm.getBackStackEntryCount(); while (entryCount-- > 0) { fm.popBackStack(); }