如何确定从Backstack恢复的片段

dvd*_*dvd 53 android acl fragment android-compatibility android-support-library

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

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

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

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

我看过如何检查片段是否从后台恢复? 但希望增加更多细节,希望这会引发答案.

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

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

所以onSaveInstanceState绝对是不可能的......

ATo*_*Tom 39

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

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

    // Do this code only first time, not after rotation or reuse fragment from backstack
}
Run Code Online (Sandbox Code Playgroud)

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

  • 这只有在你调用`setRetainInstance(true)`时才有效,这并不总是一个选项. (5认同)
  • @BenoitDuffez我相信只有你在使用`FragmentTransaction`没有添加到后栈的`Fragment`时才有必要.如果事务被添加到后台堆栈,那么"Fragment"将自动保留(即不会调用它的`onDestroy`).[**来自文档**](http://developer.android.com/guide/components/fragments.html#Transactions).如果你不将它添加到后台堆栈那么你必须像你说的那样调用`setRetainInstance()`你是否希望它不被销毁. (3认同)

Yas*_*mar 32

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.
                }
            }
        });
Run Code Online (Sandbox Code Playgroud)

使用这个addOnBackStackChangedListener.

  • 我刚试过这个,问题是在调用片段生命周期方法后调用onBackStackChanged.我想要做的是:首次创建片段时加载数据,存储数据并在需要时恢复(无重新加载).这是通过onActivityCreated中的条件加载/恢复实现的.通过弹出后台堆栈恢复片段时,请勿重新加载数据.即使我在onBackStackChanged中设置了一个标志,生命周期方法也不会看到它. (5认同)

Dav*_*vid 20

当一个片段进入后栈时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;
}
Run Code Online (Sandbox Code Playgroud)


Gio*_*fas 8

主要编辑: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();
    }
}
Run Code Online (Sandbox Code Playgroud)