【问题标题】:Difference between add(), replace(), and addToBackStack()add()、replace() 和 addToBackStack() 之间的区别
【发布时间】:2013-09-09 03:54:24
【问题描述】:

调用这些方法的主要区别是什么:

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

替换已经存在的fragment,将fragment添加到activity状态,将activity添加到back stack是什么意思?

其次,对于findFragmentByTag(),这个是搜索add()/replace()方法还是addToBackStack()方法添加的标签?

【问题讨论】:

    标签: android android-fragments


    【解决方案1】:

    1) fragmentTransaction.addToBackStack(str);

    描述 - 将此交易添加到后台堆栈。这意味着事务将在提交后被记住,并在以后从堆栈中弹出时反转其操作。

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

    描述 - 替换已添加到容器中的现有片段。这本质上与为所有当前添加的片段调用 remove(Fragment) 相同,这些片段使用相同的 containerViewId 添加,然后使用此处给出的相同参数调用 add(int, Fragment, String)。

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

    描述 - 将片段添加到活动状态。该片段还可以选择将其视图(如果 Fragment.onCreateView 返回非 null)放入 Activity 的容器视图中。

    替换已经存在的片段是什么意思,并添加 活动状态的片段并在后面添加活动 堆栈?

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

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

    当您导航到当前布局时,您可以使用该容器的 id 将其替换为您想要的片段。

    您也可以使用popBackStack() 方法返回到backStack 中的上一个片段。为此,您需要使用addToBackStack() 将该片段添加到堆栈中,然后使用commit() 进行反映。这与当前在顶部的顺序相反。

    findFragmentByTag 会搜索添加/替换添加的标签 方法还是 addToBackStack 方法?

    是否取决于您添加标签的方式。然后,它会根据您之前定义的标签找到一个片段,无论是从 XML 膨胀时还是在事务中添加时提供的标签。

    参考:FragmentTransaction

    【讨论】:

    • 那么,我可以在启动活动的开始时通过替换方法添加片段吗?
    • (之前没有添加片段)
    • 片段容器是否可以包含多个片段,如果是,则替换()方法的行为方式。它会替换该容器中的所有片段吗?或者android api有一个接受三个参数的方法,即frgamentContainer、新片段和替换对象。
    • @ved 不,它会将容器中当前存在的所有片段替换为当前片段。
    【解决方案2】:

    addreplace 之间的另一个重要区别是:

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

    对于fragment的生命周期事件onPauseonResumeonCreateView等生命周期事件,replace会被调用,add不会被调用。

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

    【讨论】:

    • 我认为一种方法是处理最顶部片段中的事件并在处理完成后调用 cancelEventDelivery()。您可以在此处找到有关 cancelEventDelivery() 方法的更多信息github.com/greenrobot/EventBus/blob/master/…
    • +1 来自我。非常重要的是要知道用新片段替换当前片段,这意味着在从片段堆栈弹出时将重新创建以前的片段以将其取回。
    • onPause,onResume 与 Host Activity 紧密相关。而且他们在更换片段时没有调用。
    • 只是添加到这一点,如果您使用 EventBus,您可以添加带有标签的片段,并将该标签从片段传递给事件,然后检查,所有事件总线都将被调用,您只需指定应该执行哪一个
    • 您必须提到您正在调用 addToBackStack() 以及 add() 或 replace() 方法。
    【解决方案3】:

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

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

    当我们将addToBackStack()add()replace() 一起使用时,我们可以看到确切的区别。

    当我们在add() 的情况下按下返回按钮时...永远不会调用onCreateView,但在replace() 的情况下,当我们按下返回按钮时......每次都会调用oncreateView。

    【讨论】:

    • 那么 add() 是否会在 android 内存方面造成更多负担,因为前一个片段的视图没有被破坏?
    • @Derekyy 是的,我想是的。
    • @Derekyy 这取决于用例。如果用户很有可能会导航到上一个屏幕,那么我认为替换会给内存带来更多负担
    【解决方案4】:

    示例 Activity 有 2 个片段,我们使用 FragmentManager 将每个片段替换/添加为 addToBackstack 到 Activity 中的布局

    使用替换

    转到 Fragment1

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

    转到 Fragment2

    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
    

    使用添加

    转到 Fragment1

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

    转到 Fragment2

    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
    

    Sample project

    【讨论】:

    • 不应该在每个 Pop 操作中在 onStop() 之前调用 onPause() 吗?
    • 区分“add()”和“replace()”的绝佳答案,尽管缺少关于 addToBackStack()。点赞
    • @ShirishHerwade 我相信他在这两种情况下都证明了用 addToBackStack 添加和替换之间的区别。
    • 这是一个比理论更好的答案
    【解决方案5】:

    虽然这是一个已经回答的老问题,但也许接下来的示例可以补充已接受的答案,并且它们对于像我这样的 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
    

    【讨论】:

    • 那么我们可以说在使用 Fragment 时,后退按钮的工作方式与 FragmentManager.popBackStack() 函数类似吗?
    【解决方案6】:

    当我们添加第一个片段时 --> 使用 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 中将第一个片段转到第二个片段 -->第二个使用 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

    【讨论】:

      【解决方案7】:

      FragmentManger 的 add 和 replace 函数可以这样描述 1.添加意味着它将在片段返回堆栈中添加片段,并将显示在您提供的给定帧 喜欢

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

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

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

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

      【讨论】:

        【解决方案8】:

        需要注意的重要事项:

        Replace 和 Replace with backstack 的区别在于,当我们仅使用 replace 时,片段被销毁(调用 ondestroy()),而当我们使用带有 backstack 的 replace 时,不调用片段 onDestroy()(即按下后退按钮时)片段通过其 onCreateView()) 调用

        【讨论】:

        【解决方案9】:

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

        所以add() 方法继续在FragmentContainer 中的前一个片段之上添加片段

        虽然replace() 方法清除所有 Containers 中的前一个Fragment,然后将其添加到FragmentContainer 中。

        什么是 addToBackStack

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

        目的是什么?

        Fragment API 与 Activity API 不同,默认情况下不带有 Back Button navigation。如果你想回到之前的 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();
        

        【讨论】:

        • 图片胜于雄辩。
        • 如果在情况 1 和 2 中我们使用“替换”代替“添加”会发生什么??
        • 很好的解释。
        • 超图解说。
        猜你喜欢
        • 2012-11-22
        • 1970-01-01
        • 1970-01-01
        • 2018-05-08
        • 2010-10-09
        相关资源
        最近更新 更多