¿Es esta la forma correcta de limpiar la pila de fragmentos al dejar una pila profundamente anidada?

StackOverflow https://stackoverflow.com/questions/5802141

Pregunta

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 dispara otro fragmento.

En el panel de selección a la izquierda tengo 5 elementos seleccionables - A B C D E.

Cada uno carga un fragmento (a través de FragmentTransaction:replace) en el panel Detalles - a b c d e

Ahora he extendido el fragmento e para contener un botón que carga otro fragmento e1 También en el panel Detalles. He hecho esto en fragmento eEl método de OnClick 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 fragmento e está en el panel de detalles. Esto está bien y lo que quiero. Sin embargo, si llego al back Botón en este punto no hace nada. Tengo que hacer clic dos veces porque e1 todavía está en la pila. Además, después de hacer clic, obtuve una excepción de puntero nulo en OnCreateview:

Para 'resolver' este problema, agregué lo siguiente cuando A B C D E se selecciona:

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?

¿Fue útil?

Solución

Bueno, hay algunas maneras de hacerlo dependiendo del comportamiento previsto, pero este enlace debería darle 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 la pila y useFragmentManager.popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE).
  • Usar FragmentManager.getBackStackEntryCount()/getBackStackEntryAt().getId()Para recuperar la identificación de la primera entrada en la pila de atrás, yFragmentManager.popBackStack(int id, FragmentManager.POP_BACK_STACK_INCLUSIVE).
  • FragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)Se supone que debe hacer toda la pila de atrás ... Creo que la documentación para eso es simplemente incorrecta. (En realidad supongo que simplemente no cubre el caso en el que pasas POP_BACK_STACK_INCLUSIVE),

Otros consejos

La otra solución limpia si no desea hacer todas las entradas de pila ...

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

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

Gracias a Joachim Respuesta, uso el código para borrar toda la entrada de la pila finalmente.

// 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 el reverso y finalmente ver Transacción Backstack y su gestió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 boques sobre todas las transacciones en el petjo y las elimina inmediatamente una a la vez.

Nota: El código anterior en algún momento no funciona y me enfrento Anr Debido a este código, así que no intente esto.

ActualizarA continuación, el método elimina todo el debate de ese "nombre" desde Backstack.

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.popBackStack("name",FragmentManager.POP_BACK_STACK_INCLUSIVE);
  • Nombre si no es nulo, este es el nombre de un estado posterior anterior para buscar; Si se encuentran, todos los estados hasta ese estado estarán explotados. los
  • POP_BACK_STACK_INCLUSION se puede usar para controlar si el estado nombrado en sí mismo está explotado. Si es nulo, solo el estado superior está explotado.

Estoy usando un código similar al que usan el bucle While, pero llamo al recuento de entrada en cada bucle ... 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();
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top