如何确定从Backstack恢复的片段

时间:2011-10-27 17:09:15

标签: android acl fragment android-support-library android-compatibility

暂时搜索此问题暂时无效:

如何确定从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 个答案:

答案 0 :(得分:38)

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

if (savedInstanceState == null && !mAlreadyLoaded) {
    mAlreadyLoaded = true;

    // Do this code only first time, not after rotation or reuse fragment from backstack
}

因为当android将片段放在backstack上时,它只会破坏它的视图,但是不会杀死实例本身,所以当从后台堆栈中恢复片段时,mAlreadyLoaded仍然是真的。

答案 1 :(得分:31)

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。

答案 2 :(得分:19)

当片段进入后台堆栈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;
}

答案 3 :(得分: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();
    }
}

答案 4 :(得分:4)

如果你将片段添加到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
    }
}

答案 5 :(得分:0)

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

答案 6 :(得分:-2)

Fragment.getFragmentManager() == null 

在添加之前和弹出之后