Diferencia entre add (), replace () y addToBackStack ()

300

¿Cuál es la principal diferencia entre llamar a estos métodos?

fragmentTransaction.addToBackStack(name);
fragmentTransaction.replace(containerViewId, fragment, tag);
fragmentTransaction.add(containerViewId, fragment, tag);

¿Qué significa reemplazar un fragmento ya existente, y agregar un fragmento al estado de actividad, y agregar una actividad a la pila posterior?

En segundo lugar, con findFragmentByTag(), ¿busca esta etiqueta agregada por el método add()/ replace()o el addToBackStack()método?

AndroidDev
fuente

Respuestas:

331

1) fragmentTransaction.addToBackStack(str);

Descripción : agregue esta transacción a la pila posterior. Esto significa que la transacción se recordará después de que se confirme y revertirá su operación cuando más tarde salga de la pila.

2) fragmentTransaction.replace(int containerViewId, Fragment fragment, String tag)

Descripción : reemplace un fragmento existente que se agregó a un contenedor. Esto es esencialmente lo mismo que llamar a remove (Fragment) para todos los fragmentos agregados actualmente que se agregaron con el mismo containerViewId y luego agregar (int, Fragment, String) con los mismos argumentos dados aquí.

3) fragmentTransaction.add(int containerViewId, Fragment fragment, String tag)

Descripción : agregue un fragmento al estado de la actividad. Este fragmento opcionalmente también puede tener su vista (si Fragment.onCreateView devuelve no nulo) en una vista de contenedor de la actividad.

¿Qué significa reemplazar un fragmento ya existente, y agregar un fragmento al estado de actividad y agregar una actividad a la pila posterior?

Hay una pila en la que se mantienen todas las actividades en el estado de ejecución. Los fragmentos pertenecen a la actividad. Para que pueda agregarlos para incrustarlos en una actividad.

Puede combinar varios fragmentos en una sola actividad para crear una interfaz de usuario de múltiples paneles y reutilizar un fragmento en múltiples actividades. Esto es esencialmente útil cuando ha definido su contenedor de fragmentos en diferentes diseños. Solo necesita reemplazar con cualquier otro fragmento en cualquier diseño.

Cuando navega hasta el diseño actual, tiene la identificación de ese contenedor para reemplazarlo con el fragmento que desea.

También puede volver al fragmento anterior en el BackStack con el popBackStack()método. Para eso necesitas agregar ese fragmento en la pila usando addToBackStack()y luego commit()para reflejar. Esto está en orden inverso con la corriente en la parte superior.

findFragmentByTag ¿busca esta etiqueta agregada por el método add / replace o el método addToBackStack?

Si depende de cómo agregaste la etiqueta. Luego, solo encuentra un fragmento por su etiqueta que definió antes, ya sea cuando se infla desde XML o como se proporciona cuando se agrega en una transacción.

Referencias: FragmentTransaction

Dios mío
fuente
2
Entonces, ¿puedo agregar fragmentos por el método de reemplazo al inicio de la actividad iniciada?
Yohanes AI
(No se agregó ningún fragmento antes)
Yohanes AI
2
¿Puede un contenedor de fragmentos contener más de un fragmento? En caso afirmativo, ¿cómo se comportará el método replace ()? Reemplazará todos los fragmentos en ese contenedor o la API de Android tiene un método que acepta tres argumentos, es decir, contenedor de fragmentos, nuevo fragmento y con quién reemplazar.
Ved
1
@ved No, reemplazará todos los fragmentos que existen actualmente en el contenedor con el actual.
reubenjohn 01 de
330

Una diferencia más importante entre addy replacees esta:

replaceelimina el fragmento existente y agrega un nuevo fragmento. Esto significa que cuando presiona el botón Atrás, el fragmento que se reemplazó se creará con su onCreateViewinvocación. Mientras que addretiene los fragmentos existentes y agrega un nuevo fragmento que significa que el fragmento existente estará activo y no estará en estado 'en pausa', por lo tanto, cuando se presiona un botón de retroceso onCreateViewno se llama al fragmento existente (el fragmento que estaba allí antes de que el nuevo fragmento fuera adicional).

En cuanto a los eventos del ciclo de vida de los fragmentos onPause, onResume, onCreateViewy otros eventos del ciclo de vida se invocarán en caso de replaceque ellos no van invocarse en caso de add.

Editar : Uno debe tener cuidado si está utilizando algún tipo de biblioteca de bus de eventos como el Eventbus de Greenrobot y reutilizando el mismo fragmento para apilar el fragmento encima de otro a través de add. En este escenario, aunque siga las mejores prácticas y registre el bus de eventos onResumey se anule el registro onPause, el bus de eventos aún estará activo en cada instancia del fragmento agregado, ya que el addfragmento no llamará a ninguno de estos métodos de ciclo de vida del fragmento. Como resultado, el oyente de bus de eventos en cada instancia activa del fragmento procesará el mismo evento que puede no ser lo que desea.

Jeevan
fuente
1
Creo que un enfoque podría ser procesar el evento en el fragmento más alto y llamar a cancelEventDelivery () después de que se complete el procesamiento. Puede encontrar más información sobre los métodos cancelEventDelivery () aquí github.com/greenrobot/EventBus/blob/master/…
Jeevan
66
+1 de mi parte Es muy importante saber que reemplazar el fragmento actual con un fragmento nuevo significa que el fragmento anterior se volverá a crear para recuperarlo cuando vuelva a aparecer desde la pila de fragmentos.
Andaluz
onPause, onResume está estrechamente asociado a la Actividad del host. Y no llamaron al reemplazar el fragmento.
Zar E Ahmer
Solo para agregar a esto, si está utilizando EventBus, puede agregar el fragmento con Etiqueta, pasar de fragmento esa etiqueta al evento y verificar de todos modos, se llamará a todos los eventbus, solo especifique cuál se debe ejecutar
usuario2582318
Debe mencionar que está llamando a addToBackStack () junto con los métodos add () o replace ().
rahil008
99

Ejemplo, una actividad tiene 2 fragmentos y usamos FragmentManagerpara reemplazar / agregar con addToBackstackcada fragmento a un diseño en la actividad

Usar reemplazar

Ir Fragmento1

Fragment1: onAttach
Fragment1: onCreate
Fragment1: onCreateView
Fragment1: onActivityCreated
Fragment1: onStart
Fragment1: onResume

Ir Fragmento2

Fragment2: onAttach
Fragment2: onCreate
Fragment1: onPause
Fragment1: onStop
Fragment1: onDestroyView
Fragment2: onCreateView
Fragment2: onActivityCreated
Fragment2: onStart
Fragment2: onResume

Fragmento Pop2

Fragment2: onPause
Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy
Fragment2: onDetach
Fragment1: onCreateView
Fragment1: onStart
Fragment1: onResume

Fragmento Pop1

Fragment1: onPause
Fragment1: onStop
Fragment1: onDestroyView
Fragment1: onDestroy
Fragment1: onDetach

Use agregar

Ir Fragmento1

Fragment1: onAttach
Fragment1: onCreate
Fragment1: onCreateView
Fragment1: onActivityCreated
Fragment1: onStart
Fragment1: onResume

Ir Fragmento2

Fragment2: onAttach
Fragment2: onCreate
Fragment2: onCreateView
Fragment2: onActivityCreated
Fragment2: onStart
Fragment2: onResume

Fragmento Pop2

Fragment2: onPause
Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy
Fragment2: onDetach

Fragmento Pop1

Fragment1: onPause
Fragment1: onStop
Fragment1: onDestroyView
Fragment1: onDestroy
Fragment1: onDetach

Proyecto de muestra

Phan Van Linh
fuente
1
¿No se onPause()suponía que debía ser llamado antes onStop()en cada acción Pop ?
iCantC
excelente respuesta para diferenciar entre 'add ()' y 'replace ()', aunque falta sobre addToBackStack (). Votación a favor
Shirish Herwade
@ShirishHerwade Creo que demostró la diferencia entre agregar y reemplazar con addToBackStack en ambos casos.
CyberShark
38

Aunque es una pregunta antigua que ya se ha respondido, tal vez los siguientes ejemplos puedan complementar la respuesta aceptada y pueden ser útiles para algunos programadores nuevos en Android como yo.

Opción 1 - "addToBackStack ()" nunca se usa

Caso 1A: agregar, eliminar y hacer clic en el botón Atrás

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
add Fragment C :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment B is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               App is closed, nothing is visible

Caso 1B: agregar, reemplazar y hacer clic en el botón Atrás

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
(replace Fragment C)    
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()
Fragment C :        onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()
Fragment C :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               App is closed, nothing is visible

Opción 2: siempre se usa "addToBackStack ()"

Caso 2A: agregar, eliminar y hacer clic en el botón Atrás

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
add Fragment C :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView()                              Fragment B is visible
(Back button clicked)
Fragment C :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment C is visible
(Back button clicked)
Fragment C :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment B is visible
(Back button clicked)
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment A is visible
(Back button clicked)
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Activity is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()                              App is closed, nothing is visible

Caso 2B: agregar, reemplazar, eliminar y hacer clic en el botón Atrás

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
(replace Fragment C)    
Fragment B :        onPause() - onStop() - onDestroyView()  
Fragment A :        onPause() - onStop() - onDestroyView() 
Fragment C :        onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView()                              Activity is visible
(Back button clicked)
Fragment C :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment C is visible
(Back button clicked)
Fragment C :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               
Fragment A :        onCreateView() - onActivityCreated() - onStart() - onResume()   
Fragment B :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment B is visible
(Back button clicked)
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment A is visible
(Back button clicked)
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Activity is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()                              App is closed, nothing is visible

Opción 3: "addToBackStack ()" no se usa siempre (en los ejemplos a continuación, w / o indica que no se usa)

Caso 3A: agregar, eliminar y hacer clic en el botón Atrás

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B w/o:     onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
add Fragment C w/o:     onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment B is visible
(Back button clicked)
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Activity is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()                              App is closed, nothing is visible

Caso 3B: agregar, reemplazar, eliminar y hacer clic en el botón Atrás

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B w/o:     onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
(replace Fragment C)    
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()   
Fragment A :        onPause() - onStop() - onDestroyView() 
Fragment C :        onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView()                              Activity is visible
(Back button clicked)
Fragment C :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment C is visible
(Back button clicked)
Fragment C :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               
Fragment A :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment A is visible
(Back button clicked)
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Activity is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()                              App is closed, nothing is visible
Javi
fuente
1
Suficientemente completo. ¡Buen esfuerzo!
pulp_fiction
Entonces, ¿podemos decir que al trabajar con fragmentos, el botón Atrás funciona de manera similar a la función FragmentManager.popBackStack ()?
Tintín
Gran respuesta, no puedo ser mejor. Esta debe ser la respuesta aceptada.
Shirish Herwade
25

La diferencia básica entre add()y replace()se puede describir como:

  • add() se usa simplemente para agregar un fragmento a algún elemento raíz.
  • replace() se comporta de manera similar pero al principio elimina los fragmentos anteriores y luego agrega el siguiente fragmento.

Podemos ver la diferencia exacta cuando la usamos addToBackStack()junto con add()o replace().

Cuando presionamos el botón de retroceso en caso de add()... onCreateView nunca se llama, pero en caso de que replace(), cuando presionamos el botón de retroceso ... se llama a oncreateView cada vez.

Avanindra_dubey
fuente
1
Entonces, ¿add () resulta en más carga en términos de memoria de Android, ya que la vista del fragmento anterior no se destruye?
Derekyy
@Derekyy Sí, creo que sí.
Arpit J.
es lo que estaba buscando
parvez rafi
2

Cuando agregamos el primer fragmento -> Segundo fragmento usando el método add ()

 btn_one.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getActivity(),"Click First 
Fragment",Toast.LENGTH_LONG).show();

                Fragment fragment = new SecondFragment();
                getActivity().getSupportFragmentManager().beginTransaction()
                        .add(R.id.fragment_frame, fragment, fragment.getClass().getSimpleName()).addToBackStack(null).commit();
//                        .replace(R.id.fragment_frame, fragment, fragment.getClass().getSimpleName()).addToBackStack(null).commit();

            }
        });

Cuando usamos add () en fragmento

E/Keshav SecondFragment: onAttach
E/Keshav SecondFragment: onCreate
E/Keshav SecondFragment: onCreateView
E/Keshav SecondFragment: onActivityCreated
E/Keshav SecondFragment: onStart
E/Keshav SecondFragment: onResume

Cuando usamos replace () en fragmento

ir al primer fragmento al segundo fragmento en Primero -> Segundo usando el método replace ()

 btn_one.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getActivity(),"Click First Fragment",Toast.LENGTH_LONG).show();

                Fragment fragment = new SecondFragment();
                getActivity().getSupportFragmentManager().beginTransaction()
//                        .add(R.id.fragment_frame, fragment, fragment.getClass().getSimpleName()).addToBackStack(null).commit();
                        .replace(R.id.fragment_frame, fragment, fragment.getClass().getSimpleName()).addToBackStack(null).commit();

            }
        });

E/Keshav SecondFragment: onAttach
E/Keshav SecondFragment: onCreate

E/Keshav FirstFragment: onPause -------------------------- FirstFragment
E/Keshav FirstFragment: onStop --------------------------- FirstFragment
E/Keshav FirstFragment: onDestroyView -------------------- FirstFragment

E/Keshav SecondFragment: onCreateView
E/Keshav SecondFragment: onActivityCreated
E/Keshav SecondFragment: onStart
E/Keshav SecondFragment: onResume

En el caso de Reemplazar primer fragmento, este método se llama de forma adicional (onPause, onStop, onDestroyView se llama de forma adicional)

E / Keshav FirstFragment: onPause

E / Keshav FirstFragment: onStop

E / Keshav FirstFragment: onDestroyView

Keshav Gera
fuente
0

La función agregar y reemplazar del FragmentManger se puede describir como estos 1. agregar significa que agregará el fragmento en la pila de fragmentos y se mostrará en el marco dado que está proporcionando como

getFragmentManager.beginTransaction.add(R.id.contentframe,Fragment1.newInstance(),null)

2. reemplazar significa que está reemplazando el fragmento con otro fragmento en el marco dado

getFragmentManager.beginTransaction.replace(R.id.contentframe,Fragment1.newInstance(),null)

La utilidad principal entre los dos es que cuando vuelva a apilar, el reemplazo actualizará el fragmento pero agregar no actualizará el fragmento anterior.

raj kavadia
fuente
0

Algo importante a tener en cuenta:

La diferencia entre Reemplazar y Reemplazar con backstack es cuando usamos solo replace, luego se destruye el fragmento (se llama a ondestroy ()) y cuando usamos replace con backstack, entonces no se llama a los fragmentos onDestroy () (es decir, cuando se presiona el botón Atrás, se invoca el fragmento con su onCreateView ())

Lloyd Dcosta
fuente
0

Aquí hay una imagen que muestra la diferencia entre add()yreplace()

ingrese la descripción de la imagen aquí

Por lo tanto, el add()método continúa agregando fragmentos sobre el fragmento anterior en FragmentContainer.

Mientras que los replace()métodos borran todo el Fragmento anterior de los Contenedores y luego lo agregan en FragmentContainer.

¿Qué es addToBackStack?

addtoBackStackEl método se puede usar con los métodos add () y replace. Tiene un propósito diferente en Fragment API.

¿Cuál es el propósito?

Fragment API a diferencia de Activity API no viene con la navegación del botón Atrás de forma predeterminada. Si desea volver al Fragmento anterior, entonces usamos el método addToBackStack () en Fragmento. Entendamos ambos

Caso 1:

getSupportFragmentManager()
            .beginTransaction()
            .add(R.id.fragmentContainer, fragment, "TAG")
            .addToBackStack("TAG")
            .commit();

ingrese la descripción de la imagen aquí

Caso 2:

getSupportFragmentManager()
            .beginTransaction()
            .add(R.id.fragmentContainer, fragment, "TAG")
            .commit();

ingrese la descripción de la imagen aquí

Rohit Singh
fuente