如何在选项卡中保持没有backstack的片段状态?

moD*_*Dev 11 tabs android android-fragments

我试图保存片段状态,onSaveInstanceState但当我回到片段时,它总是重新加载而不是从上一个状态开始.

我调查了onCreateView,onActivityCreated它总是onSaveInstanceState为空.

public void navigateFragment(String tag, Fragment fragment,
        boolean shouldAdd) {

    FragmentManager manager = getSupportFragmentManager();
    FragmentTransaction ft = manager.beginTransaction();


    if (shouldAdd)
        mStacks.get(tag).push(fragment); // push fragment on stack

    ft.replace(android.R.id.tabcontent, fragment);

    if (shouldAdd)
        ft.addToBackStack(tag);

    ft.commit();

    }
Run Code Online (Sandbox Code Playgroud)

由于我无法使用,backstack因为在标签中,堆栈没有用.任何帮助将受到高度赞赏.

Mic*_*ael 6

在这种情况下,您必须自己管理片段的状态.我不确切知道你的代码是如何工作的,所以我唯一能做的就是给你一些提示.

您需要实现的第一件事是保存片段的状态.我们假设所有片段都有唯一的ID.在这种情况下,您需要创建一个将保留所有状态的地图:

private final Map<String, Fragment.SavedState> mFragmentStates = new HashMap<>();

private void saveFragmentState(String id, Fragment fragment) {
    Fragment.SavedState fragmentState = 
            getSupportFragmentManager().saveFragmentInstanceState(fragment);
    mFragmentStates.put(id, fragmentState);
}
Run Code Online (Sandbox Code Playgroud)

您需要为要删除的片段调用此方法.然后我们需要恢复片段的状态,这就是我们如何做到这一点:

private void restoreFragmentState(String id, Fragment fragment) {
    Fragment.SavedState fragmentState = mFragmentStates.remove(id);
    if (fragmentState != null) {
        fragment.setInitialSavedState(savedState);
    }
}
Run Code Online (Sandbox Code Playgroud)

在将片段添加到事务之前需要调用此方法.

提供的代码应该可以正常工作,但为了使它在活动娱乐上正常工作,我们需要mFragmentStates正确保存和恢复:

private static final String KEY_FRAGMENT_STATES = "fragment_states";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    /* Your code ... */

    if (savedInstanceState != null) {
        Bundle fragmentStates =
                savedInstanceState.getParcelable(KEY_FRAGMENT_STATES);
        if (fragmentStates != null) {
            for (String id : fragmentStates.keySet()) {
                Fragment.SavedState fragmentState =
                        fragmentStates.getParcelable(id);
                mFragmentStates.put(id, fragmentState);
            }
        }
    }
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    /* Your code ... */

    Bundle fragmentStates = new Bundle(mFragmentStates.size());
    for (Map.Entry<String, Fragment.SavedState> entry : mFragmentStates.entrySet()) {
        fragmentStates.put(entry.getKey(), entry.getValue());
    }
    outState.putParcelable(KEY_FRAGMENT_STATES, fragmentStates);
}
Run Code Online (Sandbox Code Playgroud)

您还可以查看FragmentStatePagerAdapter类.它使用相同的方法来管理ViewPager片段的状态.

更新:所以你的代码应该看起来像这样:

private Fragment mCurrentFragment;

public void navigateFragment(String tag, Fragment fragment,
        boolean shouldAdd) {
    FragmentManager manager = getSupportFragmentManager();
    FragmentTransaction transaction = manager.beginTransaction();

    if (shouldAdd) {
        mStacks.get(tag).push(fragment); // push fragment on stack
    }

    if (mCurrentFragment != null) {
        saveFragmentState(mCurrentFragment.getClass().getName(), mCurrentFragment);
    }

    mCurrentFragment = fragment;
    restoreFragmentState(fragment.getClass().getName(), fragment);
    transaction.replace(android.R.id.tabcontent, fragment);

    if (shouldAdd) {
        // You shouldn't use back-stack when managing fragment states by yourself.
        transaction.addToBackStack(tag);
    }

    transaction.commit();
}
Run Code Online (Sandbox Code Playgroud)

在这个例子中,我使用片段的类名作为id,因此所有片段必须具有不同的类.但您可以使用任何其他唯一值作为ID.另外一件重要的事情是,在自己管理片段状态时,不应该使用反向堆栈.Back-stack执行类似的状态管理,您可能会遇到冲突.