【问题标题】:FragmentTransaction::replace() with or without addToBackStack()带或不带 addToBackStack() 的 FragmentTransaction::replace()
【发布时间】:2015-11-03 20:29:42
【问题描述】:

有一个流程来添加片段和后来的replace() 片段。所有fragment都是动态添加的,但不是全部调用addToBackStack()

getSupportFragmentManager().beginTransaction()
    .add(R.id.frgment_holder, frgmtA, frgmtA.NAME)
    .commit();

在某个地方它可以添加另一个,例如:

getSupportFragmentManager().beginTransaction()
    .replace(R.id.frgment_holder, frgmtB)
    .addToBackStack(frgmtB.NAME)
    .commit();

带有 frgmtB 的 replace() 将从容器 R.id.frgment_holder 中删除 frgmtA。 如果在此状态下按返回按钮,它将弹出 frgmtB。但是,即使添加时没有调用addToBackStack(),它会重新创建frgmtA吗?

如果在将片段添加到同一个容器中的流程中,使用连续的 add() 和 replace() 调用,并且有人调用 addToBackStack() 但有人没有,那么后退按钮的行为会如何?

编辑: 之后

getSupportFragmentManager().beginTransaction()
        .replace(R.id.frgment_holder, frgmtB)
        .addToBackStack(frgmtB.NAME)
        .commit();

getSupportFragmentManager().findFragmentByTag(frgmtA.NAME);

仍然找到frgmtA?如果添加 frgmtA 时也调用 addToBackStack();

文档说“这首先搜索当前添加到管理器活动的片段;如果没有找到这样的片段,则搜索当前在后台堆栈上的所有片段。”

情况会是

  1. 添加 frgmtA;不调用添加到堆栈;此处的 UI 状态已更改;

(如果 frgmtA 不是由 add() 动态添加,而是在布局文件中用 class="frgmtA" 进行了分隔怎么办?)。

  1. 用 frgmtB 替换(); addToStack();

  2. 用 frgmtC 替换(); addToStack();

那么如果 stackTop 是 frgmtC,希望按下后退按钮以带回第一个 frgmtA 及其最后的 UI 状态。

【问题讨论】:

    标签: android android-fragments fragment-backstack


    【解决方案1】:

    1.

    .add(R.id.frgment_holder, frgmtA, frgmtA.NAME)
                .commit();
    .replace(R.id.frgment_holder, frgmtB, frgmtB.NAME)
            .addToBackStack(frgmtB.NAME)
            .commit();`
    

    replace 将从持有者中移除 frgmtA,并且将调用其 onDestroyView(但由于它在 backstack 的事务数据中被引用,因此 frgmtA 不会被销毁)。并且 frgmtB 将被添加到持有者中。 由于 frgmtA 没有被破坏,所以

    getSupportFragmentManager().findFragmentByTag(frgmtA.NAME); 
    

    会找到的。

    然后,按下后​​退按钮,它将从 backStack 中弹出顶部交易,然后将交易撤消。即从持有人中删除 frgmtB 并将 frgmtA 添加回持有人。由于不再引用 frgmtB,因此调用了 onDestroy。

    2。 在

    的情况下
    add frgmtA;
    replace() with frgmtB; addToStack();
    replace() with frgmtC; addToStack(); 
    

    如果想后按跳转到frgmtA,需要重写onBackPressed(),在里面 做

    popBackStack(frgmtB.NAME, POP_BACK_STACK_INCLUSIVE), 
    

    这将丢弃堆栈中名为 frgmtB.NAME 的堆栈条目上方的事务,并在其上反转事务,这将添加回持有者中的 frgmtA。

    【讨论】:

    • 在我工作了大约 4 个小时后,您节省了我的时间,谢谢 (:
    【解决方案2】:

    除非您使用onBackPressed()addOnBackStackChangedListener() 干扰“后退”按钮逻辑,否则一切都会顺利进行

    • 如果你通过addToBackStack()添加片段,点击返回后会被移除
    • 如果后台堆栈中没有其他碎片,应用程序将被关闭

    【讨论】:

    • 谢谢迪米塔!但仍不清楚从容器中删除先前片段的 replace() 是什么意思。如果前一个片段也调用了 addToBackStack(),remove() 的“删除”是破坏之前的片段,还是将它们缓存在某个地方?
    • replace() 将删除容器中具有提供的 id 的所有现有片段。没有缓存。如果你想将replace()addToBackStack() 结合起来,那么事情就会变得沉重。您需要保留调用commit() 时返回的正整数的引用。这将是您的后台堆栈 ID。我建议远离复杂的场景,因为这很容易让你失去理智:) add()/remove() 选择碎片而不是用 replace() 轰炸它们,或者改变碎片的用途。
    • 同意使用简单的添加/删除让操作系统来处理推送/弹出。但是,如果还需要涵盖用户管理的流程,那么“简单”的推送/弹出也无济于事(这就是混乱的来源)。就像问题中所说的情况,有三个片段,fA,fB,fC,。 fA 使用 add() 添加或定义为 xml 持有者中的类; fB 和 fC 是稍后添加的(可以使用 add() 或 replace() 完成)和 addToBackStack。如果它在 fC 上有按钮单击返回 fA,似乎没有办法(因为 fA 在持有人中),除非全部弹出并创建一个新的 fA 从头开始​​添加。
    【解决方案3】:

    根据您的要求试试这个任何人行

    你已经检查了它的 4 个不同的行代码

    getActivity().getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    
    getActivity().getSupportFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    
        FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.framelayout, fragment);
        transaction.addToBackStack(null);
    
        getActivity().getSupportFragmentManager().popBackStack();
    

    【讨论】:

      猜你喜欢
      • 2012-11-22
      • 2013-09-09
      • 2014-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-07
      • 2017-07-28
      • 2013-06-07
      相关资源
      最近更新 更多