Разница между add (), replace () и addToBackStack ()


300

В чем основное различие между вызовом этих методов:

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

Что значит заменить уже существующий фрагмент, добавить фрагмент в состояние активности и добавить действие в задний стек?

Во- вторых, с findFragmentByTag(), делает этот поиск тега добавлено add()/ replace()метод или addToBackStack()метод?

Ответы:


331

1) fragmentTransaction.addToBackStack(str);

Описание - Добавить эту транзакцию в задний стек. Это означает, что транзакция будет запомнена после ее фиксации, и будет отменять свою работу, когда позднее будет извлечена из стека.

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

Описание - заменить существующий фрагмент, который был добавлен в контейнер. По сути, это то же самое, что вызов метода remove (Fragment) для всех добавленных в данный момент фрагментов, которые были добавлены с тем же containerViewId, а затем добавлены (int, Fragment, String) с теми же аргументами, что и здесь.

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

Описание - добавить фрагмент в состояние активности. Этот фрагмент может также иметь свое представление (если Fragment.onCreateView возвращает ненулевое значение) в контейнерное представление действия.

Что значит заменить уже существующий фрагмент, добавить фрагмент в состояние активности и добавить действие в задний стек?

Существует стек, в котором хранятся все действия в рабочем состоянии. Фрагменты относятся к деятельности. Таким образом, вы можете добавить их, чтобы включить их в упражнение.

Вы можете объединить несколько фрагментов в одном действии, чтобы создать многопанельный пользовательский интерфейс и повторно использовать фрагмент в нескольких действиях. Это особенно полезно, когда вы определили свой контейнер фрагментов в разных макетах. Вам просто нужно заменить любой другой фрагмент в любом макете.

Когда вы переходите к текущему макету, у вас есть идентификатор этого контейнера, чтобы заменить его нужным фрагментом.

Вы также можете вернуться к предыдущему фрагменту в backStack с помощью popBackStack()метода. Для этого вам нужно добавить этот фрагмент в стек, используя addToBackStack()и затем commit()отражать. Это в обратном порядке с током сверху.

findFragmentByTag выполняет ли этот поиск тег, добавленный методом добавления / замены или методом addToBackStack?

Если зависит от того, как вы добавили тег. Затем он просто находит фрагмент по тегу, который вы определили ранее, либо при накачке из XML, либо при добавлении при добавлении в транзакцию.

Ссылки: FragmentTransaction


2
Итак, могу ли я добавить фрагмент методом замены в начале действия?
Йоханес А.И.

(Фрагмент не был добавлен ранее)
Йоханес А.И.

2
Может ли контейнер фрагментов содержать более одного фрагмента, если да, то как будет вести себя метод replace (). Если он заменит все фрагменты в этом контейнере или Android API, есть метод, который принимает три аргумента, то есть frgamentContainer, новый фрагмент и кем заменить.
вед

1
@ved Нет, он заменит все существующие в контейнере фрагменты на текущий.
Рувимджон

330

Еще одно важное различие между addи replaceэто:

replaceудаляет существующий фрагмент и добавляет новый фрагмент. Это означает, что при нажатии кнопки «Назад» будет создан фрагмент, который был заменен onCreateView. Принимая во внимание, addчто существующие фрагменты сохраняются и добавляется новый фрагмент, что означает, что существующий фрагмент будет активным, и они не будут находиться в состоянии «приостановлено», поэтому при нажатии кнопки «Назад» onCreateViewне вызывается для существующего фрагмента (фрагмент, который был там до того, как новый фрагмент был добавлено).

С точки зрения событий жизненного цикла фрагмента onPause, onResume, onCreateViewи другие события жизненного цикла будет вызываться в случае , replaceно они не будут вызываться в случае add.

Редактировать : нужно быть осторожным, если она использует какую-то библиотеку шины событий, такую как Eventrobot Greenrobot, и повторно использует тот же фрагмент, чтобы поместить фрагмент поверх другого через add. В этом сценарии, даже если вы будете следовать рекомендациям и зарегистрировать шину событий onResumeи отменить ее регистрацию onPause, шина событий будет по-прежнему активна в каждом экземпляре добавленного фрагмента, поскольку addфрагмент не будет вызывать ни один из этих методов жизненного цикла фрагмента. В результате прослушиватель шины событий в каждом активном экземпляре фрагмента будет обрабатывать одно и то же событие, которое может не соответствовать вашему желанию.


1
Я думаю, что один из подходов может заключаться в обработке события в самом верхнем фрагменте и вызове cancelEventDelivery () после завершения обработки. Вы можете найти более о cancelEventDelivery () методы здесь github.com/greenrobot/EventBus/blob/master/...
Дживан

6
+1 от меня. Очень важно знать, что замена текущего фрагмента новым фрагментом означает, что предыдущий фрагмент будет воссоздан, чтобы получить его обратно при возврате из стека фрагментов.
AndaluZ

onPause, onResume тесно связан с деятельностью хоста. И они не звонили при замене фрагмента.
Зар Э Ахмер

Просто добавьте к этому, что если вы используете EventBus, вы можете добавить фрагмент с тегом и передать от фрагмента этот тег к событию и в любом случае проверить, будет ли вызван весь eventbus, вы просто указываете, какой из них должен выполняться
user2582318

Вы должны упомянуть, что вы вызываете addToBackStack () вместе с методами add () или replace ().
rahil008

100

Пример действия имеет 2 фрагмента, и мы используем FragmentManagerдля замены / добавления addToBackstackкаждого фрагмента в макет в действии

Используйте заменить

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

Pop Fragment2

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

Pop Fragment1

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

Используйте добавить

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

Pop Fragment2

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

Pop Fragment1

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

Пример проекта


1
не onPause()должен был быть вызван раньше onStop()на каждом поп- акции?
iCantC

отличный ответ, чтобы различать 'add ()' и 'replace ()', хотя отсутствует в addToBackStack (). Upvote
Шириш Хервейд

@ShirishHerwade Я полагаю, он продемонстрировал разницу между add и replace с addToBackStack в обоих случаях.
CyberShark

38

Хотя на этот старый вопрос уже дан ответ, возможно, эти следующие примеры могут дополнить принятый ответ, и они могут быть полезны для некоторых новых программистов в Android, как и я.

Вариант 1 - «addToBackStack ()» никогда не используется

Случай 1А - добавление, удаление и нажатие кнопки «Назад»

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

Случай 1B - добавление, замена и нажатие кнопки «Назад»

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

Вариант 2 - «addToBackStack ()» всегда используется

Случай 2А - добавление, удаление и нажатие кнопки «Назад»

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

Случай 2B - добавление, замена, удаление и нажатие кнопки «Назад»

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

Вариант 3 - «addToBackStack ()» используется не всегда (в приведенных ниже примерах без указания указывает, что он не используется)

Случай 3А - добавление, удаление и нажатие кнопки «Назад»

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

Случай 3B - добавление, замена, удаление и нажатие кнопки «Назад»

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
Достаточно тщательно. Хорошее усилие!
pulp_fiction

Можно ли сказать, что при работе с фрагментами кнопка «Назад» работает аналогично функции FragmentManager.popBackStack ()?
Тинтин

отличный ответ, не может быть лучше. Это должен быть принят ответ.
Шириш Хервейд

25

Основное различие между add()и replace()может быть описано как:

  • add() используется для простого добавления фрагмента в некоторый корневой элемент.
  • replace() ведет себя аналогично, но сначала удаляет предыдущие фрагменты, а затем добавляет следующий фрагмент.

Мы можем увидеть точную разницу, когда мы используем addToBackStack()вместе с add()или replace().

Когда мы нажимаем кнопку «назад» после, в случае add()... onCreateView никогда не вызывается, но в случае replace(), когда мы нажимаем кнопку «назад», oncreateView вызывается каждый раз.


1
Таким образом, add () приводит к большей нагрузке с точки зрения памяти Android, так как предыдущий фрагмент не уничтожен?
Дерекий

@Derekyy Да, я так думаю.
Арпит Дж.

это то, что я искал
Парвез Рафи

2

Когда мы добавляем первый фрагмент -> второй фрагмент, используя метод 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();

            }
        });

Когда мы используем add () во фрагменте

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

Когда мы используем replace () во фрагменте

переход от первого фрагмента ко второму фрагменту в First -> Second с использованием метода 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

В случае замены первого фрагмента этот метод вызывается дополнительно (onPause, onStop, onDestroyView вызывается дополнительно)

E / Keshav Первый фрагмент: onPause

E / Keshav FirstFragment: onStop

E / Keshav Первый фрагмент: onDestroyView


0

Функция добавления и замены FragmentManger может быть описана как эти 1. add означает, что она добавит фрагмент в задний стек фрагмента и покажет в заданном кадре, который вы предоставляете, как

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

2.relace означает, что вы заменяете фрагмент другим фрагментом в данном кадре.

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

Основная утилита между ними заключается в том, что когда вы вернетесь в стек, замена обновит фрагмент, но добавление не обновит предыдущий фрагмент.


0

Важно отметить, что:

Разница между Replace и Replace with backstack заключается в том, что всякий раз, когда мы используем только replace, фрагмент уничтожается (вызывается ondestroy ()), а когда мы используем замену backstack, фрагменты onDestroy () не вызываются (т. Е. При нажатии кнопки back фрагмент вызывается с его onCreateView ())


0

Вот картина, которая показывает разницу между add()иreplace()

введите описание изображения здесь

Таким образом, add()метод продолжает добавлять фрагменты поверх предыдущего фрагмента в FragmentContainer.

Хотя replace()методы удаляют весь предыдущий фрагмент из контейнеров, а затем добавляют его в FragmentContainer.

Что такое addToBackStack

addtoBackStackМетод можно использовать с методами add () и replace. Это служит другой цели в API Фрагмента.

Какова цель?

API фрагментов, в отличие от API действий, по умолчанию не включает навигацию по кнопке «Назад ». Если вы хотите вернуться к предыдущему фрагменту, тогда мы используем метод addToBackStack () во фрагменте. Давайте разберемся как

Случай 1:

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

введите описание изображения здесь

Случай 2:

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

введите описание изображения здесь

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.