Diferença entre add (), replace () e addToBackStack ()

300

Qual é a principal diferença entre chamar esses métodos:

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

O que significa substituir um fragmento já existente, adicionar um fragmento ao estado da atividade e adicionar uma atividade à pilha traseira?

Em segundo lugar, com findFragmentByTag(), essa pesquisa por tag adicionada pelo método add()/ replace()ou pelo addToBackStack()método?

AndroidDev
fonte

Respostas:

331

1) fragmentTransaction.addToBackStack(str);

Descrição - adicione esta transação à pilha traseira. Isso significa que a transação será lembrada após ser confirmada e reverterá sua operação quando mais tarde sair da pilha.

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

Descrição - Substitua um fragmento existente que foi adicionado a um contêiner. Isso é essencialmente o mesmo que chamar remove (Fragment) para todos os fragmentos adicionados atualmente que foram adicionados com o mesmo containerViewId e, em seguida, add (int, Fragment, String) com os mesmos argumentos fornecidos aqui.

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

Descrição - adicione um fragmento ao estado da atividade. Opcionalmente, esse fragmento também pode ter sua visualização (se Fragment.onCreateView retornar não nulo) em uma visualização de contêiner da atividade.

O que significa substituir um fragmento já existente e adicionar um fragmento ao estado da atividade e adicionar uma atividade à pilha traseira?

Há uma pilha na qual todas as atividades no estado de execução são mantidas. Fragmentos pertencem à atividade. Então você pode adicioná-los para incorporá-los em uma atividade.

Você pode combinar vários fragmentos em uma única atividade para criar uma interface do usuário com vários painéis e reutilizar um fragmento em várias atividades. Isso é essencialmente útil quando você define seu contêiner de fragmentos em diferentes layouts. Você só precisa substituir por qualquer outro fragmento em qualquer layout.

Ao navegar para o layout atual, você tem o ID desse contêiner para substituí-lo pelo fragmento desejado.

Você também pode voltar ao fragmento anterior no backStack com o popBackStack()método Para isso, você precisa adicionar esse fragmento na pilha usando addToBackStack()e depois commit()para refletir. Isso está na ordem inversa com a corrente no topo.

findFragmentByTag esta busca pela tag adicionada pelo método add / replace ou pelo método addToBackStack?

Se depende de como você adicionou a tag. Em seguida, ele apenas encontra um fragmento por sua tag que você definiu antes, quando inflado a partir do XML ou como fornecido quando adicionado a uma transação.

Referências: FragmentTransaction

Meu Deus
fonte
2
Então, posso adicionar fragmentos pelo método de substituição na atividade iniciada?
Yohanes AI
(Nenhum fragmento foi adicionado antes)
Yohanes AI
2
Um contêiner de fragmento pode conter mais de um fragmento? Se sim, como o método replace () se comportará. Ele substitui todos os fragmentos nesse contêiner ou API do Android e possui um método que aceita três argumentos, ou seja, frgamentContainer, novo fragmento e com quem substituir.
ved
1
@ved Não, ele substituirá todos os fragmentos atualmente existentes no contêiner pelo atual.
Reubenjohn
330

Mais uma diferença importante entre adde replaceé esta:

replaceremove o fragmento existente e adiciona um novo fragmento. Isso significa que, quando você pressionar o botão Voltar, o fragmento que foi substituído será criado com a onCreateViewinvocação. Considerando que addretém os fragmentos existentes e adiciona um novo fragmento, o que significa que o fragmento existente estará ativo e eles não estarão no estado 'pausado', portanto, quando um botão voltar é pressionado, onCreateViewo fragmento existente não é chamado (o fragmento que existia antes do fragmento novo ser adicionado).

Em termos de eventos do ciclo de vida de fragmento onPause, onResume, onCreateViewe outros eventos de ciclo de vida vai ser invocado em caso de replacemas eles não vão ser invocada em caso de add.

Edit : Deve-se ter cuidado se ela estiver usando algum tipo de biblioteca de barramento de eventos como o Eventbus da Greenrobot e reutilizar o mesmo fragmento para empilhá-lo em cima de outro via add. Nesse cenário, mesmo que você siga as práticas recomendadas e registre onResumee cancele o registro do onPausebarramento de eventos, o barramento de eventos ainda estará ativo em cada instância do fragmento adicionado, pois o addfragmento não chamará nenhum desses métodos de ciclo de vida do fragmento. Como resultado, o ouvinte do barramento de eventos em cada instância ativa do fragmento processaria o mesmo evento, que pode não ser o que você deseja.

Jeevan
fonte
1
Penso que uma abordagem poderia ser processar o evento no fragmento superior e chamar cancelEventDelivery () após a conclusão do processamento. Você pode encontrar mais sobre a cancelEventDelivery () métodos aqui github.com/greenrobot/EventBus/blob/master/...
Jeevan
6
+1 de mim. Muito importante saber que a substituição do fragmento atual por um novo fragmento significa que o fragmento anterior será recriado para recuperá-lo ao retornar da pilha de fragmentos.
precisa saber é o seguinte
onPause, onResume está fortemente associado à atividade do host. E eles não ligaram ao substituir o fragmento.
Zar E Ahmer 08/08
Apenas para adicionar isso, se você estiver usando o EventBus, poderá adicionar o fragmento com Tag, passar do fragmento para o evento e verificar de qualquer maneira, todos os eventbus serão chamados, basta especificar qual deles deve ser executado
user2582318
Você deve mencionar que está chamando addToBackStack () junto com os métodos add () ou replace ().
rahil008
99

Exemplo de uma atividade tem 2 fragmentos e usamos FragmentManagerpara substituir / adicionar com addToBackstackcada fragmento a um layout na atividade

Use substituir

Go Fragment1

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

Go Fragment2

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 add

Go Fragment1

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

Go Fragment2

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

Projeto de exemplo

Phan Van Linh
fonte
1
não onPause()deveria ter sido chamado antes onStop()em toda ação pop ?
ICantC 02/10/19
excelente resposta para diferenciar 'add ()' e 'replace ()', embora falte em addToBackStack (). Upvote
Shirish Herwade 28/11/19
@ShirishHerwade Acredito que ele demonstrou diferença entre adicionar e substituir com addToBackStack nos dois casos.
CyberShark
38

Embora seja uma pergunta antiga já respondida, talvez os próximos exemplos possam complementar a resposta aceita e possam ser úteis para alguns novos programadores no Android como eu.

Opção 1 - "addToBackStack ()" nunca é usado

Caso 1A - adicionando, removendo e clicando no botão Voltar

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 - adicionando, substituindo e clicando no botão Voltar

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

Opção 2 - "addToBackStack ()" é sempre usado

Caso 2A - adicionando, removendo e clicando no botão Voltar

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 - adicionando, substituindo, removendo e clicando no botão Voltar

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

Opção 3 - "addToBackStack ()" nem sempre é usado (nos exemplos abaixo, sem / indica que não é usado)

Caso 3A - adicionando, removendo e clicando no botão Voltar

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 - adicionando, substituindo, removendo e clicando no botão Voltar

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
fonte
1
Completamente suficiente. Bom esforço!
Pulp_fiction 27/07/19
Então, podemos dizer que, ao trabalhar com fragmentos, o botão Voltar funciona de maneira semelhante à função FragmentManager.popBackStack ()?
Tintin
ótima resposta, não posso ser melhor. Essa resposta deve ser aceita.
Shirish Herwade 29/11/19
25

Diferença básica entre add()e replace()pode ser descrita como:

  • add() é usado simplesmente para adicionar um fragmento a algum elemento raiz.
  • replace() se comporta de maneira semelhante, mas a princípio remove os fragmentos anteriores e depois adiciona o próximo fragmento.

Podemos ver a diferença exata quando usamos addToBackStack()junto com add()ou replace().

Quando pressionamos o botão voltar depois, no caso de add()... onCreateView nunca é chamado, mas no caso de replace(), quando pressionamos o botão voltar ... oncreateView é chamado sempre.

Avanindra_dubey
fonte
1
Então add () resulta em mais carga em termos de memória android, já que a visão do fragmento anterior não é destruída?
precisa saber é o seguinte
@ Derekyy Sim, acho que sim.
Arpit J. 14/01
é o que eu estava procurando
parvez rafi 09/06
2

Quando adicionamos primeiro fragmento -> segundo fragmento usando o 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();

            }
        });

Quando usamos add () no 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

Quando usamos replace () no fragmento

indo do primeiro fragmento para o segundo fragmento em Primeiro -> Segundo usando o 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

No caso de Substituir primeiro fragmento, esse método é chamado extra (onPause, onStop, onDestroyView é chamado extra)

E / Keshav FirstFragment: onPause

E / Keshav FirstFragment: onStop

E / Keshav FirstFragment: onDestroyView

Keshav Gera
fonte
0

A função add e replace do FragmentManger pode ser descrita como 1. 1. add significa que ele adicionará o fragmento na pilha traseira do fragmento e será exibido em um determinado quadro que você está fornecendo como

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

2.replace significa que você está substituindo o fragmento por outro fragmento no quadro especificado

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

O utilitário principal entre os dois é que, quando você estiver empilhando novamente, a substituição atualizará o fragmento, mas o add não atualizará o fragmento anterior.

raj kavadia
fonte
0

É importante notar:

A diferença entre Replace e Replace with backstack é sempre que usamos apenas replace, então o fragmento é destruído (ondestroy () é chamado) e quando usamos replace with backstack, os fragmentos onDestroy () não são chamados (ou seja, quando o botão voltar é pressionado, o fragmento é chamado com seu onCreateView ())

Lloyd Dcosta
fonte
0

Aqui está uma imagem que mostra a diferença entre add()ereplace()

insira a descrição da imagem aqui

Portanto, o add()método continua adicionando fragmentos sobre o fragmento anterior no FragmentContainer.

Enquanto os replace()métodos limpam todo o fragmento anterior dos contêineres e o adicionam no FragmentContainer.

O que é addToBackStack

addtoBackStackO método pode ser usado com os métodos add () e substitua. Ele serve a um propósito diferente na Fragment API.

Qual é o propósito?

A API de fragmentos, diferentemente da Activity API, não vem com a navegação no botão Voltar por padrão. Se você deseja voltar ao Fragmento anterior, usamos o método addToBackStack () no Fragmento. Vamos entender os dois

Caso 1:

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

insira a descrição da imagem aqui

Caso 2:

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

insira a descrição da imagem aqui

Rohit Singh
fonte