Fragmentos todavía agregados a backstack sin llamar addToBackStack, ¿por qué?

Hago mi clase de ayudante del cambiador del fragmento y tengo cierto problema con él.

Lo llamo FragmentChanger

Tiene un fragmentContainer , que es un ViewGroup , que contiene todos los fragmentos que me gustaría mostrar.

He hecho mi propio replace(Fragment fragmentToChange, boolean needSaveToBackStack)

Función que es:

  • Quitar el fragmento antiguo del fragmento Container
  • Añadiendo un nuevo fragmento al fragmentoContainer
  • Opcionalmente se guarda en backStack, si needSaveToBackStack es true o false .

El error es el siguiente:

Si utilizo mi función de reemplazo con el ahorro al backStack que está funcionando correctamente, puedo utilizar el botón posterior de mi dispositivo para retroceder y volver a los fragmentos preventiously agregados que trabaja como un encanto.

Pero cuando me gustaría reemplazar un fragmento con ahorrar a backStack, hay algo mal en mi código porque cuando retrocedo, puedo ver en la pantalla el fragmento que NO agregé al backStack , y TAMBIÉN puedo ver otro Fragmento añadido previsiously al mismo tiempo!

Así que puedo ver 2 fragmentos al mismo tiempo, así:

Introduzca aquí la descripción de la imagen

Este es mi código:

 //It is my helper class to handle replacing fragments. public class FragmentChanger { // fragmentTransaction FragmentTransaction fragmentTransaction; // the container for fragments ViewGroup fragmentContainer; // activity ofc Activity act; // Ctr: adding a default fragment to be the first so we can see it at app // start public FragmentChanger(Activity act, ViewGroup container, Fragment startingFragment) { this.act = act; this.fragmentContainer = container; fragmentTransaction = act.getFragmentManager().beginTransaction(); fragmentTransaction.add(container.getId(), startingFragment, startingFragment.getClass().getSimpleName()); fragmentTransaction.addToBackStack(startingFragment.getClass().getSimpleName()); fragmentTransaction.commit(); } // Replacing a fragment with an other one public void replace(Fragment fragmentToChange, boolean needSaveToBackStack) { fragmentTransaction = act.getFragmentManager().beginTransaction(); // replacing old fragment to the new one! fragmentTransaction.replace(fragmentContainer.getId(), fragmentToChange, fragmentToChange.getClass().getSimpleName()); // Some null checking, and if the new fragment is NOT equals the current // fragment if (getCurrentFragment() != null && getCurrentFragment() != fragmentToChange) { /*** Important** because something here is wrong ***/ // only addToBackStack when i want it, when needSaveToBackStack = // true! if (needSaveToBackStack) { fragmentTransaction.addToBackStack(fragmentToChange.getClass().getSimpleName()); } } // commiting changes fragmentTransaction.commit(); } // getting current Fragment private Fragment getCurrentFragment() { try { FragmentManager fragmentManager = act.getFragmentManager(); String fragmentTag = fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName(); Fragment currentFragment = act.getFragmentManager().findFragmentByTag(fragmentTag); return currentFragment; } catch (Exception ex) { ex.printStackTrace(); } return null; } // Logging the back stack public void logBackStack() { Log("Logging back stack:", "============="); FragmentManager fragmentManager = act.getFragmentManager(); int stackSize = fragmentManager.getBackStackEntryCount(); Log("Fragments count on the stack: ", stackSize + ""); for (int i = 0; i < stackSize; i++) { String fragmentTag = fragmentManager.getBackStackEntryAt(i).getName(); Log("Fragment on the stack: ", fragmentTag); } } private void Log(String str, String msg) { Log.i(str, msg); } } 

Y esta es mi MainActivity donde probar mi clase de ayuda de fragmento:

 public class MainActivity extends Activity implements OnClickListener { // My 3 Fragment Classes, could be N other type, // in this example I only got 3 FragmentA fragmentA; FragmentB fragmentB; FragmentC fragmentC; // Button to add the fragments manually Button addA, addB, addC; // This is my activity's container, its a simple viewGroup // could be anything that can hold fragments ViewGroup fragmentContainer; // This is my fragment changer helper class that need some revision by you // guys FragmentChanger fragmentChanger; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //defining my adding buttons addA = (Button)findViewById(R.id.addAbtn); addB = (Button)findViewById(R.id.addBbtn); addC = (Button)findViewById(R.id.addCbtn); //setting onclicklistenrs addA.setOnClickListener(this); addB.setOnClickListener(this); addC.setOnClickListener(this); // defining my main container, this will holds fragments fragmentContainer = (ViewGroup) findViewById(R.id.fragmentContainer); // defining my fragments, each of them got an Activity (this), a // Container (mainContainer), and a Layout ofc. fragmentA = new FragmentA(this, fragmentContainer, R.layout.fragment_a_layout); fragmentB = new FragmentB(this, fragmentContainer, R.layout.fragment_b_layout); fragmentC = new FragmentC(this, fragmentContainer, R.layout.fragment_c_layout); // defining my fragment changer with an activity(this), a // container(mainContent) and a starting fragment to show! fragmentChanger = new FragmentChanger(this, fragmentContainer, fragmentA); } @Override public void onClick(View view) { if (view.equals(addA)) { //When adding fragmentA, i always want to save it to backstack fragmentChanger.replace(fragmentA, true); } else if (view.equals(addB)) { //I dont want to save to back stack when adding B //So if i press back button, i dont want to see fragmentB ever again. //(But i do see, this is the error.) fragmentChanger.replace(fragmentB, false); } else if (view.equals(addC)) { //When adding fragmentC, i always want to save it to backstack fragmentChanger.replace(fragmentC, true); } //After any modification on fragments, i log the backstack fragmentChanger.logBackStack(); } 

}

Ps: Puedo ver claramente que fragmentB nunca está en el backStack si registro la pila cada vez que reemplazo un fragmento con mi clase de ayuda. Entonces, ¿por qué aparece si vuelvo a pulsar el botón?

Aprecio mucho cualquier consejo, este es mi primer intento con el uso de fragmentos con mi propia clase de ayudante y me gustaría hacer que sea muy útil.

Así que aquí lo que encontré mal con su código:

1) Estás mezclando etiquetas de Fragment y BackStackEntry .

 String fragmentTag = fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName(); 

Así que aquí está recibiendo la etiqueta de BackStackEntry (no Fragment ), que agrega o no en fragmentTransaction.addToBackStack() . Por lo tanto, usted está recibiendo el estado equivocado y utilizarlo como fragmento actual.

2) Generalmente no es una buena idea almacenar y reutilizar fragmentos como lo hace en sus campos de clase: FragmentA fragmentA; . Puede conducir a problemas con el estado y la inflación, es mejor crearlos en cada transacción, si usted no quiere resolver puzzles adicionales.

Intenta reemplazar el fragmento utilizando el método FragmentTransacion.replace como se muestra en el enlace aquí.

Y puedes referir este ejemplo también. Esto funciona para mí perfectamente.

En primer lugar en el constructor de su clase FragmentChanger que está agregando todos los fragmentos en su backstack. Ya que se están agregando en orden que se están agregando como A, B y luego C. Después de añadir a la pila de retroceso en ese orden que están haciendo más transacciones en la parte superior de la misma. Al inicializarlos, evítelos agregarlos al backstack. Sólo agrega / quita mientras hace el clic del botón real.

Hay un montón de reemplazos en su código por lo que no sé cómo realmente solucionar esto, pero puedo dar una visión general de lo que debe hacer.

Si desea agregar un fragmento al backStack, haga un .replace(params ).addToBackStack(Tag)

Si no desea agregar un fragmento en particular, simplemente omita la línea addToBackStack(Tag) completamente.

También se puede cambiar tu getCurrentFragment() a

Fragment currentFrag=getFragmentManager().findFragmentById(R.id.fragment_container);

Lea esta RESPUESTA aquí para una mejor explicación y también esta RESPUESTA

  • Pantalla completa DialogFragment se superpone con StatusBar
  • FragmentPagerAdapter - evita la recreación de las vistas de fragmentos
  • Fragmento ciclo de vida: cuando "ondestroy" y "ondestroyview" no son llamados?
  • Implementación de desplazamiento entre pestañas mediante tab-host en Android
  • Android Wear - Añadir icono por encima de CardFragment
  • No se puede establecer la propiedad en un fragmento con varias instancias
  • Java.lang.NullPointerException: Intenta invocar el método virtual 'int android.view.View.getImportantForAccessibility ()' en una referencia de objeto nulo
  • Fragmento de la pestaña, Crear vista cada vez que la pestaña cambia
  • Android: onPostResume se llama después de que se reanude el fragmento
  • El fragmento de niño se destruye sin ninguna buena razón
  • Android Fragments recreado en el cambio de orientación
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.