使用addToBackStack进行Fragment事务后点击返回按钮无效

7

我希望能通过使用addToBackStack()来撤销replace FragmentTransaction

FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();         
Fragment scheduleFragment = new ScheduleFragment();     
fragmentTransaction.replace(R.id.content_container, scheduleFragment, "scheduleFragment");
fragmentTransaction.addToBackStack("scheduleFragment");
fragmentTransaction.commit();

但是之后,点击返回按钮没有任何反应。
根据文档,它应该撤销交易。
我漏掉了什么?

2
文档(参见“为片段实现后退导航”)建议使用.add而不是.replace。请查看此处的答案:https://dev59.com/N2Ml5IYBdhLWcg3wKkTW,但我想`.replace`并没有得到完全支持,而`.add`似乎可以正常工作。 - electrocrat
@Abel Paz的下面的回答是正确的解决.replace问题的方法。 - electrocrat
4个回答

25

正确的做法是使用 onBackPressed() 方法来捕获应用程序中的后退事件,然后使用 popBackStack() "弹出" 后退栈。例如:

正确的方法是在你的应用程序中使用 onBackPressed() 方法来捕获后退事件,然后使用 popBackStack() 来“弹出”后退栈。例如:

public void onBackPressed()
{
    // Catch back action and pops from backstack
    // (if you called previously to addToBackStack() in your transaction)
    if (getSupportFragmentManager().getBackStackEntryCount() > 0){
        getSupportFragmentManager().popBackStack();
    }
    // Default action on back pressed
    else super.onBackPressed();
}

PD:抱歉回答晚了,但我刚看到你的问题。希望能对你有所帮助!


那为什么在Android文档中,他们传达了错误的方式。:( - Kamalakannan J
2
我认为这个逻辑是不必要的。如果您使用addToBackStack,应用程序将完全相同。 - IgorGanapolsky
与所有文档指向这些结构的使用方式相反,我也只能在 OnBackPressed 中添加此代码才能使其按预期工作:/ - bc3tech
此外,看起来这意味着 Android 文档中的这部分是完全错误的 http://developer.android.com/training/implementing-navigation/temporal.html#back-fragments - "当后退栈上有 FragmentTransaction 对象并且用户按下 Back 按钮时,FragmentManager 弹出最近的事务并执行相反的操作(例如,如果事务添加了一个片段,则删除该片段)"。 - bc3tech
如果您在活动中覆盖了onBackPressed()方法,FragmentTransaction将无法直接使用。因此,需要检查返回堆栈的计数并手动弹出返回堆栈。 - JItesh SUvarna

4
尝试使用fragmentTransaction.addToBackStack(null)addToBackStack()方法的参数是返回状态的可选名称,你不需要在replace()方法中使用该标记,它只是片段的可选标记。 你可以在这里阅读更多相关信息:点击这里

是的,您可以保留用于引用片段的标记,但使用 addToBackStack(null) 会起作用吗?如果使用它会发生什么? - Ryan Smith
我没有尝试过,因为这对我来说没有意义。所以我实现了自己的“Fragment”堆栈(请看我的回答)。 - jul
2
你的答案是可行的,但我认为它是不必要的。当你使用addToBackStack()时,你不需要传递片段或其标签,而是传递堆栈的名称以便将其添加到其中。当你查看文档时,它说“name An optional name for this back stack state, or null”,其中name是字符串参数。我认为你可以只使用addToBackStack(null),这至少值得一试。 - Ryan Smith

2

已经有一段时间了,但我希望这能帮到某个人。

fragmentTransaction.addToBackStack(null) 如果你正在扩展 AppCompatActivity,将不起作用。它在 Activity 中可以很好地工作。我找不到原因。


0

我实现了自己的Fragment堆栈:

public Fragment addFragmentToStack(Fragment fragment){
    if(MyApplication.fragmentStack.size()>20){
        MyApplication.fragmentStack.remove(0);
    }
    return MyApplication.fragmentStack.push(fragment);
}   

public void onBackPressed() {
        if (MyApplication.fragmentStack.size() > 0) {
            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.replace(R.id.content_container, MyApplication.fragmentStack.pop());
            ft.commit();
        }
        else{
            finish();
        }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接