Java 在 popBackStack 之后调用哪个方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22870210/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 18:34:12  来源:igfitidea点击:

Which method is being called after popBackStack?

javaandroidandroid-fragments

提问by OpenHaus

I have an activity where I am calling three fragments - each depending on each other:

我有一个活动,我在其中调用了三个片段 - 每个片段都相互依赖:

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

A(ctivity) -> f1(片段一,标题{is|should}:列表)-> f2(片段二,标题{is|should}:概览)-> f3(片段三,标题{is|should}:细节)

ATM I use the following method call to jump backwards:

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

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

This works fine.

这工作正常。

I am overriding the ActionBar title in each fragment like this:

我像这样覆盖每个片段中的 ActionBar 标题:

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

When navigating forward (like shown above) this works flawlessly but navigating backwards the title of the ActionBar isn′t updated:

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

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

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

Obviously I could just update it again when the fragment is shown. But my debugger never stops in any of the methods I′d except which would be called like onResume().

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

So is there actually any method being called in a previous fragment after popBackStack()?

那么在popBackStack()之后的前一个片段中实际上是否有任何方法被调用?

回答by SimonSays

You can find a nice Fragmentlifecycle diagram in the android docs here. So yes, if the fragment is brought to the foreground from the backstack onCreateView(), onActivityCreated(), onStart()and onResume()are called.

您可以Fragment此处的 android 文档中找到一个不错的生命周期图。所以,是的,如果该片段从堆栈中带到前台onCreateView()onActivityCreated()onStart()onResume()被调用。

回答by jejer

I use following workaround:

我使用以下解决方法:

1) set 1st fragment setHasOptionsMenu(false)before add 2nd fragment on top of 1st one.

1)setHasOptionsMenu(false)在第一个片段的顶部添加第二个片段之前设置第一个片段。

2) set 1st fragment setHasOptionsMenu(true)in onOptionsItemSelected()after return from 2nd fragment.

2)setHasOptionsMenu(true)onOptionsItemSelected()从第二个片段返回后设置第一个片段。

3) onCreateOptionsMenu()of 1st fragment should be called and you can change actionbar here.

3)onCreateOptionsMenu()应该调用第一个片段,您可以在此处更改操作栏。

But I want to know a better solution.

但我想知道一个更好的解决方案。

回答by kehers

My workaround is to get the current title of the actionbar in the Fragment before setting it to the new title. This way, once the Fragment is popped, I can change back to that title.

我的解决方法是先获取 Fragment 中操作栏的当前标题,然后再将其设置为新标题。这样,一旦 Fragment 弹出,我就可以改回那个标题。

@Override
public void onResume() {
    super.onResume();
    // Get/Backup current title
    mTitle = ((ActionBarActivity) getActivity()).getSupportActionBar()
            .getTitle();
    // Set new title
    ((ActionBarActivity) getActivity()).getSupportActionBar()
        .setTitle(R.string.this_fragment_title);
}

@Override
public void onDestroy() {
    // Set title back
    ((ActionBarActivity) getActivity()).getSupportActionBar()
        .setTitle(mTitle);

    super.onDestroy();
}

回答by Manisha

use addOnBackStackChangedListener method in your BaseActivity, which will be called any time backstack changes

在 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);
                            }
                        }
                    }
                }
            });

回答by Burkely91

I know this is a bit late for an answer but for anyone who navigates here this might help!

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

First thing is first: popBackStack()doesn't pop a fragment, it pops a fragment transaction. So the last fragment transaction is reversed upon being called. If you were displaying FragmentA currently and your transaction was:

首先是第一件事:popBackStack() 不弹出片段,而是弹出片段事务。所以最后一个片段事务在被调用时被逆转。如果您当前正在显示 FragmentA 并且您的交易是:

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

It would replace FragmentA with FragmentB, and add that transaction (not the fragment) to the back stack. If you then hit the back button, it pops the transaction off the back stack, which was "replace this FragmentA with a FragmentB". Essentially, this instruction reverses the last transaction and removes it from the stack of transactions carried out. If the original FragmentA still exists, it uses that one. If it's been destroyed, it makes a new one.

它将用 FragmentB 替换 FragmentA,并将该事务(而不是片段)添加到返回堆栈中。如果您随后按下后退按钮,它会将事务从后退堆栈中弹出,即“用 FragmentB 替换此 FragmentA”。本质上,该指令反转最后一个事务并将其从执行的事务堆栈中删除。如果原始 FragmentA 仍然存在,则使用该 FragmentA。如果它被破坏了,它会产生一个新的。

So, if the Fragment hasn't been destroyed, then recalling the fragment after using on popBackStack(), the onStart() and onResume() methods are called. If the Fragment has been destroyed previously, then the lifecycle methods will be called starting from onAttach(). It's the same as pressing the back button on Activities.

所以,如果 Fragment 没有被销毁,那么在使用 popBackStack() 后调用该 Fragment,onStart() 和 onResume() 方法被调用。如果之前已经销毁了 Fragment,那么生命周期方法将从 onAttach() 开始被调用。这与按活动上的后退按钮相同。

Now the important bit, what happens re fragment lifecycle when we pop off back stack? Well as said before the fragment transaction is reversed so:

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

Scenario 1: Your fragmentB didn't already exist before transaction. In this case the onCreate() and onAttach() methods are called during the transaction so the fragment will be destroyed and detached if you call popBackStack() and reverse the transaction (Note FragmentA probably already existed so replacing it wont destroy it as we're not undoing a fragment creation). In this case the lifecycle methods will be called starting from onAttach().

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

Scenario 2: Your fragmentB did already exist before transaction. In this case the fragment won't be destroyed and the next time you access it the onStart() and onResume() methods are called.

场景二:你的fragmentB在交易前就已经存在了。在这种情况下,片段不会被销毁,下次访问它时将调用 onStart() 和 onResume() 方法。

Fragment Lifecycle

片段生命周期

This fellow here explains a few things about using popbackstack() http://vinsol.com/blog/2014/09/19/transaction-backstack-and-its-management/and the fragment lifecycle http://vinsol.com/blog/2014/10/22/fragment-view-state-retention-a-dirty-solution/. The other related posts are worth reading too!

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

回答by stdout

There's also one other good sourcethat you can read through.

您还可以通读另一个很好的来源

I think, the important point is the difference of the transaction you performed on Fragment B. If it's add, then no lifecycle methods are called on Fragment A, if it's replace, you will get some calls on those methods.

我认为,重要的一点是你在 Fragment B 上执行的事务的不同。如果是add,那么在Fragment A上不会调用生命周期方法,如果是replace,你会得到一些对这些方法的调用。