在popBackStack之后调用哪种方法?

2022-09-01 08:53:37

我有一个活动,我称之为三个片段 - 每个片段相互依赖:

A(ctivity) -> f1 (Fragment one, title {is|should}: list) -> f2 (Fragment two, title {is|should}: overview) -> f3 (Fragment three, title {is|should}: detail)

ATM 我使用以下方法调用向后跳转:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            FragmentManager fragmentManager = getSupportFragmentManager();
            if (fragmentManager.getBackStackEntryCount()>0){
                fragmentManager.popBackStack();
            }
    }
}

这工作正常。

我正在覆盖每个片段中的 ActionBar 标题,如下所示:

ActionBar bar = getSherlockActivity().getSupportActionBar();
bar.setTitle(R.string.title_f3);

向前导航(如上所示)时,这可以完美地工作,但向后导航时,ActionBar的标题不会更新:

f3 (title {is|should}: detail) -> f2 (title {is}: detail, {should}: overview) -> f1 (title {is}: detail, {should}: list)

显然,当片段显示时,我可以再次更新它。但是我的调试器永远不会停止我的任何方法,除了像onResume()这样的调用。

那么在popBackStack()之后的上一个片段中实际上有什么方法被调用吗?


答案 1

我知道对于答案来说这有点晚了,但对于任何在这里导航的人来说,这可能会有所帮助!

第一件事是第一件事:popBackStack()不会弹出一个片段,它会弹出一个片段事务。因此,最后一个片段事务在被调用时被反转。如果您当前显示 FragmentA 并且您的交易是:

fragmentTransaction.replace(R.id.your_layout, fragmentB);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();

它将用 FragmentB 替换 FragmentA,并将该事务(而不是片段)添加到后退堆栈。如果你然后点击后退按钮,它会从后退堆栈中弹出交易,即“用SequenceB替换这个FragmentA”。从本质上讲,此指令反转最后一个事务,并将其从执行的事务堆栈中删除。如果原始 FragmentA 仍然存在,它将使用该片段。如果它被摧毁了,它就会变成一个新的。

因此,如果片段尚未销毁,则在使用popBackStack()后调用片段,将调用onStart()和onResume()方法。如果片段之前已被销毁,则将从 onAttach() 开始调用生命周期方法。这与按下“活动”上的后退按钮相同。

现在重要的一点是,当我们从后堆栈中弹出时,碎片生命周期会发生什么?正如在片段交易被逆转之前所说,所以:

场景 1:您的片段 B 在事务之前尚不存在。在这种情况下,onCreate() 和 onAttach() 方法在事务期间被调用,因此,如果您调用 popBackStack() 并反转事务,片段将被销毁和分离(注意 FragmentA 可能已经存在,因此替换它不会破坏它,因为我们没有撤消片段创建)。在这种情况下,生命周期方法将从 onAttach() 开始调用。

场景 2:您的片段 B 在事务之前已存在。在这种情况下,片段不会被销毁,下次访问它时,将调用 onStart() 和 onResume() 方法。

Fragment Lifecycle

这里的这个家伙解释了一些关于使用popbackstack()http://vinsol.com/blog/2014/09/19/transaction-backstack-and-its-management/ 和片段生命周期 http://vinsol.com/blog/2014/10/22/fragment-view-state-retention-a-dirty-solution/ 的事情。其他相关帖子也值得一读!


答案 2

在 BaseActivity 中使用 addOnBackStackChangedListener 方法,只要 backstack 更改,就会调用该方法。

getSupportFragmentManager().addOnBackStackChangedListener(
            new FragmentManager.OnBackStackChangedListener() {
                public void onBackStackChanged() {
                    FragmentManager fm = getSupportFragmentManager();

                    if (fm != null) {
                        int backStackCount = fm.getBackStackEntryCount();
                        if (backStackCount == 0) {
                            if (getSupportActionBar() != null) {
                                getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);
                            }
                            setToolbarTittle(R.string.app_name);
                        } else {
                            if (getSupportActionBar() != null) {
                                getSupportActionBar().setHomeAsUpIndicator(R.drawable.back);
                            }
                        }
                    }
                }
            });

推荐