首页 文章

如何确定从Backstack恢复的片段

提问于
浏览
50

一直在寻找这个问题但现在无济于事:

如何确定片段是从backstack恢复?我在FragmentActivity中使用兼容性库和ListFragment . 选择ListFragment中的项目时,将启动新的片段以替换ListFragment .

我注意到当FragmentActivity暂停时,会调用Fragment的onSaveInstanceState . 但是当Fragment通过FragmentTransaction放入后端堆栈时,onSaveInstanceState不会被调用,那么使用null savedInstanceState Bundle调用生命周期方法onCreateView和onActivityCreated .

我问这个是因为我想在创建或恢复Fragment时加载一些数据,但是当用户通过它回来时却不是这样 . 堆栈中 .

我已经看了How to check if Fragment was restored from a backstack?但想要添加更多细节,希望这会引发答案 .

编辑:刚注意到http://developer.android.com/reference/android/app/Fragment.html#onSaveInstanceState(android.os.Bundle)

但请注意:可以在onDestroy()之前的任何时间调用此方法 . 在许多情况下,片段可能大部分被拆除(例如放置在没有显示UI的后台堆栈上),但是在其拥有的活动实际上需要保存其状态之前,其状态将不会被保存 .

所以onSaveInstanceState肯定是不可能的......

7 回答

  • 16
    getSupportFragmentManager().addOnBackStackChangedListener(new OnBackStackChangedListener() {    
                public void onBackStackChanged() {
                    Log.i(TAG, "back stack changed ");
                    int backCount = getSupportFragmentManager().getBackStackEntryCount();
                    if (backCount == 0){
                                       // block where back has been pressed. since backstack is zero.
                    }
                }
            });
    

    使用此addOnBackStackChangedListener .

  • 8

    MAJOR EDIT :2013年10月15日

    当应用程序放到后台并返回到前台时,前面的解释(保留在下面以供参考)失败 .

    相反,最好将后台堆叠的当前大小与创建碎片并放入后台堆叠时的大小进行比较 .


    http://developer.android.com/guide/components/fragments.html#Creating中仔细看看图2

    这个数字告诉你的是,当从backstack恢复一个片段时,它的onCreate()不会被调用,而它的onCreateView()就是 .


    所以,你可能想做这样的事情:

    public class MyFragment extends Fragment {
        int mBackStackSize = 0;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mBackStackSize = getFragmentManager().getBackStackEntryCount();
        }
    
        public boolean isRestoredFromBackstack() {
            return mBackStackSize > getFragmentManager().getBackStackEntryCount();
        }
    }
    
  • -1

    我认为最简单的方法是在onViewCreated()方法中执行此操作:

    if (savedInstanceState == null && !mAlreadyLoaded) {
        mAlreadyLoaded = true;
    
        // Do this code only first time, not after rotation or reuse fragment from backstack
    }
    

    因为当android将片段放在backstack上时,它只会破坏它的视图,但是不会杀死实例本身,因此当从backstack恢复片段时,mAlreadyLoaded仍然是真的 .

  • 0

    如果你将片段添加到backstack,并在一些操作后使用fragmentTransaction.hide(片段)隐藏它,然后从backstack恢复它,如fragmentTransaction.show(fragmentManager.findFragmentByTag(fragment.getName()));你可以覆盖onHiddenChanged(布尔隐藏)

    @Override
    public void onHiddenChanged(boolean hidden) {
        // TODO Auto-generated method stub
        super.onHiddenChanged(hidden);
        if (!hidden) {
            //fragment became visible
            //your code here
        }
    }
    
  • 37

    在某些情况下,您可以使用isVisible方法来了解它是首先显示片段还是从backstack恢复 .

  • 4

    当一个片段进入后台堆栈时 onDestroyView() 被调用 . 不是 onDestroy() .

    当一个片段从后台堆栈 onCreateView() 调用时弹出 . 不是 onCreate() .

    所以添加一个 boolean mIsRestoredFromBackstack 到片段,如下所示:

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        mIsRestoredFromBackstack = false;
    }
    
    @Override
    public void onResume()
    {
        super.onResume();
        if(mIsRestoredFromBackstack)
        {
            // The fragment restored from backstack, do some work here!
        }
    }
    
    @Override
    public void onDestroyView()
    {
        super.onDestroyView();
        mIsRestoredFromBackstack = true;
    }
    
  • 31
    Fragment.getFragmentManager() == null
    

    在添加之前和弹出之后

相关问题