add(),replace()和addToBackStack()之间的区别


300

调用这些方法之间的主要区别是:

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

替换一个已经存在的片段,并向活动状态添加一个片段,并向后堆栈添加活动,这意味着什么?

其次,使用findFragmentByTag(),此搜索是否搜索add()/ replace()方法或addToBackStack()方法添加的标记?

Answers:


330

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返回非空)进入活动的容器视图。

替换一个已经存在的片段,并向活动状态添加一个片段,并向后堆栈添加活动,这意味着什么?

有一个堆栈,其中所有处于运行状态的活动都被保留。片段属于活动。因此,您可以添加它们以将其嵌入活动中。

您可以在一个活动中组合多个片段以构建多窗格UI,并在多个活动中重用一个片段。当您在不同的布局中定义了片段容器时,这实际上很有用。您只需要用任何布局中的任何其他片段替换即可。

导航到当前布局时,您具有该容器的ID,可将其替换为所需的片段。

您还可以使用方法返回到backStack中的上一个片段popBackStack()。为此,您需要使用将该片段添加到堆栈中addToBackStack(),然后commit()进行反映。这是相反的顺序,电流在最上面。

findFragmentByTag会搜索由add / replace方法或addToBackStack方法添加的标签吗?

是否取决于您如何添加标签。然后,它只是通过您定义的标签找到一个片段,该片段在从XML扩展时或在事务中添加时提供时就已定义。

参考:FragmentTransaction


2
因此,我可以在开始的活动开始时通过替换方法添加片段吗?
Yohanes AI 2014年

(之前未添加任何片段)
Yohanes AI

2
片段容器可以包含多个片段吗,如果是,则replace()方法的行为如何。它将替换该容器中的所有碎片或android api有一个接受三个参数的方法,即frgamentContainer,新片段和替换对象。
ved

1
@ved否,它将用当前片段替换容器中当前存在的所有片段。
reubenjohn

329

add和之间的另一个重要区别replace是:

replace删除现有片段并添加新片段。这意味着当您按下“后退”按钮时,将创建替换后的片段onCreateView并被调用。而add保留现有片段并添加新片段,这意味着现有片段将处于活动状态,因此不会处于“已暂停”状态,因此在按下“后退”按钮时onCreateView时不要求现有的片段(其是片段那里之前新片段添加)。

就片段的生命周期事件而言 onPauseonResumeonCreateView和其他生命周期事件将在以下情况下调用replace,但他们不会在以下情况下被调用add

编辑:如果她正在使用某种事件总线库(例如Greenrobot的Eventbus)并重用相同的片段,以将片段堆叠到其他via上, 则应格外小心add。在这种情况下,即使您遵循最佳实践并在其中注册了事件总线onResume并在其中注销了该onPause事件,在添加的片段的每个实例中事件总线仍将处于活动状态,因为add片段不会调用这两个片段生命周期方法中的任何一个。结果,片段的每个活动实例中的事件总线侦听器都将处理可能不是您想要的同一事件。


1
我认为一种方法可能是在最上面的片段中处理事件,并在处理完成后调用cancelEventDelivery()。您可以在这里github.com/greenrobot/EventBus/blob/master/…上
Jeevan

6
向我+1。知道用新片段替换当前片段非常重要,这意味着从片段堆栈弹出时将重新创建以前的片段以将其取回。
AndaluZ '16

onPause,onResume与主机活动紧密相关。而且在替换片段时他们没有打电话。
Zar E Ahmer '16

只是添加到此,如果您使用的是EventBus,则可以添加带有Tag的片段,并将该片段从片段传递到事件,然后进行检查,所有事件总线都将被调用,您只需指定应执行的
事件总线即可

必须提到的是,您正在与add()或replace()方法一起调用addToBackStack()。
rahil008

99

例如,一个活动有2个片段,我们用每个片段FragmentManager替换/添加addToBackstack到活动中的布局

使用替换

去片段1

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

去片段2

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

流行片段2

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

流行片段1

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

使用添加

去片段1

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

去片段2

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

流行片段2

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

流行片段1

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

样例项目


1
难道不 onPause()应该onStop()在每次Pop动作之前都被调用吗?
iCantC

区分“ add()”和“ replace()”的绝佳答案,尽管缺少addToBackStack()。Upvote
Shirish Herwade

@ShirishHerwade我相信他在两种情况下都演示了add和replace用addToBackStack的区别。
Cyber​​Shark

38

尽管这是一个已经解决的老问题,但是也许下一个示例可以补充已接受的答案,对于像我这样的Android新程序员来说,它们可能很有用。

选项1-从未使用过“ addToBackStack()”

情况1A-添加,删除并单击“后退”按钮

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()”

情况2A-添加,删除并单击“后退”按钮

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()”(在以下示例中,w / o表示未使用)

情况3A-添加,删除并单击“后退”按钮

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_fiction19年

那么我们可以说在使用片段时,后退按钮的工作方式与FragmentManager.popBackStack()函数类似吗?
丁丁

很好的答案,再好不过了。这应该被接受。
Shirish Herwade

25

add()和之间的基本区别replace()可以描述为:

  • add() 用于仅将片段添加到某些根元素。
  • replace() 行为类似,但起初它会删除先前的片段,然后添加下一个片段。

当我们addToBackStack()add()replace()

当我们在add()... 之后不replace()按下on按钮时,onCreateView不会被调用,但在情况下,当我们按下back ...时,每次都会调用oncreateView。


1
那么由于前一个片段的视图没有被破坏,add()是否会给Android内存带来更多负担?
Derekyy

@Derekyy是的,我是这样认为的。
Arpit J.

这就是我想要的
parvez rafi

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()时

在第一个->第二个中使用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

如果是Replace First Fragment,则额外调用这些方法(onPause,onStop,onDestroyView额外调用)

E / Keshav FirstFragment:onPause

E / Keshav FirstFragment:onStop

E / Keshav FirstFragment:onDestroyView


0

FragmentManger的功能add和replace可以描述如下:1. add表示它将片段添加到片段堆栈中,并在给定的帧处显示,例如

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

2.replace表示您要在给定帧处用另一个片段替换该片段

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

两者之间的主要实用程序是,当您进行反向堆叠时,替换将刷新片段,但添加将不刷新先前的片段。


0

要注意的重要事项:

使用backstack进行替换和替换之间的区别是,每当我们仅使用replace时,该片段就会被销毁(调用ondestroy()),而当我们使用backstack进行replace时,则不会调用片段onDestroy()(即,当按下后退按钮时,调用片段)及其onCreateView()


0

这是一张图片,显示了add()和之间的区别replace()

在此处输入图片说明

所以,add()方法不断增加碎片之上在FragmentContainer的先前片段。

虽然replace()方法清除了所有从容器中以前的片段,然后将其添加到FragmentContainer中。

什么是addToBackStack

addtoBackStack该方法可以与add()和replace方法一起使用。在Fragment API中,它具有不同的用途。

目的是什么?

与Activity API不同,Fragment API 默认情况下不带有“ 后退按钮”导航。如果要返回到上一个Fragment,则可以在Fragment中使用addToBackStack()方法。让我们都了解

情况1:

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

在此处输入图片说明

情况2:

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

在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.