Differenza tra add (), replace () e addToBackStack ()


300

Qual è la differenza principale tra la chiamata di questi metodi:

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

Che cosa significa sostituire un frammento già esistente e aggiungere un frammento allo stato di attività e aggiungere un'attività allo stack posteriore?

In secondo luogo, con findFragmentByTag(), questa ricerca di tag aggiunto dal metodo add()/ replace()o dal addToBackStack()metodo?

Risposte:


331

1) fragmentTransaction.addToBackStack(str);

Descrizione : aggiungere questa transazione allo stack posteriore. Ciò significa che la transazione verrà ricordata dopo essere stata impegnata e ne annullerà l'operazione quando successivamente verrà espulsa dallo stack.

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

Descrizione : sostituisce un frammento esistente che è stato aggiunto a un contenitore. Questo è essenzialmente lo stesso di chiamare remove (Fragment) per tutti i frammenti attualmente aggiunti che sono stati aggiunti con lo stesso containerViewId e quindi aggiungere (int, Fragment, String) con gli stessi argomenti forniti qui.

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

Descrizione : aggiunge un frammento allo stato dell'attività. Questo frammento può anche avere la sua vista (se Fragment.onCreateView restituisce un valore non nullo) in una vista contenitore dell'attività.

Che cosa significa sostituire un frammento già esistente e aggiungere un frammento allo stato dell'attività e aggiungere un'attività allo stack posteriore?

C'è uno stack in cui vengono mantenute tutte le attività nello stato in esecuzione. I frammenti appartengono all'attività. Quindi puoi aggiungerli per incorporarli in un'attività.

È possibile combinare più frammenti in una singola attività per creare un'interfaccia utente a più riquadri e riutilizzare un frammento in più attività. Ciò è essenzialmente utile quando hai definito il contenitore dei frammenti in diversi layout. Hai solo bisogno di sostituire con qualsiasi altro frammento in qualsiasi layout.

Quando si passa al layout corrente, si dispone dell'ID di quel contenitore per sostituirlo con il frammento desiderato.

Puoi anche tornare al frammento precedente nel backStack con il popBackStack()metodo Per questo è necessario aggiungere quel frammento nello stack usando addToBackStack()e quindi commit()riflettere. Questo è in ordine inverso con la corrente in alto.

findFragmentByTag cerca questa tag aggiunta dal metodo add / replace o dal metodo addToBackStack?

Se dipende da come hai aggiunto il tag. Quindi trova solo un frammento dal suo tag che hai definito prima o quando gonfiato da XML o come fornito quando aggiunto in una transazione.

Riferimenti: FragmentTransaction


2
Quindi, posso aggiungere frammento con il metodo di sostituzione all'inizio dell'attività avviata?
Yohanes AI,

(Nessun frammento è stato aggiunto prima)
Yohanes AI

2
Un contenitore di frammenti può contenere più di un frammento? Se sì, come si comporterà il metodo replace (). Sostituirà tutti gli frammenti in quel contenitore o API Android hanno un metodo che accetta tre argomenti, vale a dire frgamentContainer, nuovo frammento e con chi sostituire.
visto il

1
@ved No, sostituirà tutti i frammenti attualmente esistenti nel contenitore con quello corrente.
reubenjohn,

330

Un'altra importante differenza tra added replaceè questa:

replacerimuove il frammento esistente e aggiunge un nuovo frammento. Ciò significa che quando si preme il pulsante Indietro, il frammento che è stato sostituito verrà creato con il suo onCreateViewrichiamo. Considerando che addmantiene i frammenti esistenti e aggiunge un nuovo frammento che significa che il frammento esistente sarà attivo e non saranno nello stato "in pausa", quindi quando viene premuto un pulsante indietro onCreateViewnon viene richiesto per il frammento esistente (il frammento che era lì prima del nuovo frammento era aggiunto).

In termini di eventi del ciclo di vita di frammento onPause, onResume, onCreateViewed altri eventi del ciclo di vita saranno invocate in caso di replace, ma si suole essere richiamati in caso di add.

Modifica : si dovrebbe fare attenzione se sta usando una specie di libreria di bus di eventi come Eventbus di Greenrobot e riutilizzando lo stesso frammento per impilare il frammento sopra l'altro tramite add. In questo scenario, anche se si seguono le migliori pratiche e si registra il bus degli eventi onResumee si annulla la registrazione onPause, il bus degli eventi sarebbe comunque attivo in ogni istanza del frammento aggiunto poiché il addframmento non chiamerà nessuno di questi metodi del ciclo di vita del frammento. Di conseguenza, il listener del bus eventi in ogni istanza attiva del frammento elaborerebbe lo stesso evento che potrebbe non essere quello desiderato.


1
Penso che un approccio potrebbe essere quello di elaborare l'evento nel frammento più in alto e chiamare cancelEventDelivery () al termine dell'elaborazione. Puoi trovare ulteriori informazioni sui metodi cancelEventDelivery () qui github.com/greenrobot/EventBus/blob/master/…
Jeevan

6
+1 da me. È molto importante sapere che la sostituzione del frammento corrente con un nuovo frammento significa che il frammento precedente verrà ricreato per recuperarlo quando si ritorna indietro dalla pila di frammenti.
AndaluZ,

onPause, onResume è strettamente associato all'attività dell'host. E non hanno chiamato quando hanno sostituito il frammento.
Zar E Ahmer,

Solo per aggiungere a questo, se si utilizza EventBus è possibile aggiungere il frammento con Tag e passare dal frammento di quel tag all'evento e controllare comunque, tutti gli eventbus verranno chiamati, è sufficiente specificare quale deve essere eseguito
user2582318

Devi menzionare che stai chiamando addToBackStack () insieme ai metodi add () o replace ().
rahil008,

99

Esempio un'attività ha 2 frammenti e usiamo FragmentManagerper sostituire / aggiungere con addToBackstackogni frammento un layout in attività

Usa sostituisci

Vai frammento 1

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

Vai frammento2

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

Frammento Pop2

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

Frammento Pop1

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

Usa aggiungi

Vai frammento 1

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

Vai frammento2

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

Frammento Pop2

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

Frammento Pop1

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

Progetto di esempio


1
non onPause()doveva essere chiamato prima onStop()in ogni azione pop ?
iCantC,

risposta eccellente per distinguere tra 'add ()' e 'replace ()', sebbene manchi di addToBackStack (). Upvote
Shirish Herwade,

@ShirishHerwade Credo che abbia dimostrato la differenza tra aggiungere e sostituire con addToBackStack in entrambi i casi.
CyberShark

38

Sebbene sia una vecchia domanda a cui è già stata data una risposta, forse i prossimi esempi possono integrare la risposta accettata e possono essere utili per alcuni nuovi programmatori in Android come lo sono io.

Opzione 1: "addToBackStack ()" non viene mai utilizzato

Caso 1A: aggiunta, rimozione e clic sul pulsante Indietro

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: aggiunta, sostituzione e clic sul pulsante Indietro

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

Opzione 2: "addToBackStack ()" viene sempre utilizzato

Caso 2A: aggiunta, rimozione e clic sul pulsante Indietro

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: aggiunta, sostituzione, rimozione e clic sul pulsante Indietro

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

Opzione 3: "addToBackStack ()" non viene sempre utilizzato (negli esempi seguenti, senza indicare che non viene utilizzato)

Caso 3A: aggiunta, rimozione e clic sul pulsante Indietro

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: aggiunta, sostituzione, rimozione e clic sul pulsante Indietro

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

1
Abbastanza approfondito. Buon sforzo!
pulp_fiction,

Quindi possiamo dire che mentre si lavora con i frammenti il ​​pulsante Indietro funziona in modo simile alla funzione FragmentManager.popBackStack ()?
Tintin,

ottima risposta, non posso essere migliore. Questa dovrebbe essere una risposta accettata.
Shirish Herwade,

25

La differenza di base tra add()e replace()può essere descritta come:

  • add() è usato semplicemente per aggiungere un frammento a qualche elemento radice.
  • replace() si comporta in modo simile ma all'inizio rimuove i frammenti precedenti e quindi aggiunge il frammento successivo.

Possiamo vedere la differenza esatta quando usiamo addToBackStack()insieme a add()o replace().

Quando premiamo il pulsante indietro in caso di add()... onCreateView non viene mai chiamato, ma in caso di replace(), quando premiamo il pulsante indietro ... oncreateView viene chiamato ogni volta.


1
Quindi, add () risulta in un maggiore carico in termini di memoria Android, poiché la vista del frammento precedente non viene distrutta?
Derekyy,

@Derekyy Sì, penso di sì.
Arpit J.

è quello che stavo cercando
parvez rafi

2

Quando aggiungiamo il primo frammento -> Secondo frammento usando il metodo 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();

            }
        });

Quando usiamo add () nel frammento

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

Quando utilizziamo sostituire () nel frammento

andando al primo frammento al secondo frammento in First -> Second usando il metodo 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

In caso di Sostituisci primo frammento, questo metodo viene chiamato in più (onPause, onStop, onDestroyView viene chiamato in più)

E / Keshav FirstFragment: onPause

E / Keshav FirstFragment: onStop

E / Keshav FirstFragment: onDestroyView


0

La funzione di aggiunta e sostituzione di FragmentManger può essere descritta in quanto 1. aggiungi significa che aggiungerà il frammento nello stack posteriore del frammento e mostrerà in un determinato frame che stai fornendo come

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

2. Sostituisci significa che stai sostituendo il frammento con un altro frammento in corrispondenza del frame specificato

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

L'utilità principale tra i due è che quando si sta eseguendo il back stacking, il sostituto aggiornerà il frammento ma aggiungi non aggiornerà il frammento precedente.


0

Cosa importante da notare:

La differenza tra Sostituisci e Sostituisci con backstack è ogni volta che usiamo solo sostituisci quindi il frammento viene distrutto (viene chiamato ondestroy ()) e quando usiamo sostituisci con backstack allora i frammenti suDestroy () non vengono chiamati (cioè quando viene premuto il pulsante indietro viene richiamato il frammento con il suo onCreateView ())


0

Ecco un'immagine che mostra la differenza tra add()ereplace()

inserisci qui la descrizione dell'immagine

Quindi il add()metodo continua ad aggiungere frammenti sopra il frammento precedente in FragmentContainer.

Mentre i replace()metodi cancella tutto il frammento precedente dai contenitori e quindi lo aggiunge in FragmentContainer.

Che cos'è addToBackStack

addtoBackStackIl metodo può essere utilizzato con i metodi add () e sostituisci. Serve a uno scopo diverso nell'API Fragment.

Qual è lo scopo?

L'API del frammento a differenza dell'API dell'attività non viene fornita con la navigazione del pulsante Indietro per impostazione predefinita. Se vuoi tornare al frammento precedente, allora usiamo il metodo addToBackStack () in frammento. Comprendiamo entrambi

Caso 1:

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

inserisci qui la descrizione dell'immagine

Caso 2:

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

inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.