从FragmentStatePagerAdapter中删除片段

Jak*_*ubW 9 android android-fragments

UPDATE

经过一番与这个问题的重大斗争和SO用户的帮助后,我设法解决了这个问题.这就是我clearProgressUpTo现在的样子.

    public void clearProgressUpTo(int progress) {
    boolean deleted = false;

    for (int i = fragments.size() - 1; i > 0; i--) {
        int key = fragments.keyAt(i);
        if (key != progress) {
            fragments.delete(key);
            deleted = true;
        } else {
            break;
        }
    }

    if (deleted)
        notifyDataSetChanged(); //prevents recursive call (and IllegalStateException: Recursive entry to executePendingTransactions)

    while (mSavedState.size() > progress) {
        mSavedState.remove(mSavedState.size()-1);
    }

}
Run Code Online (Sandbox Code Playgroud)

我之所以这样做notifyDataSetChanged是因为initiateItemmSavedState再次填满了我.而且我确信在通知我之后我adapter不会持有任何这些Fragments.

此外,如果你想这样做改变你的mSaveState,protected所以你将能够从扩展类(在我的情况下VerticalAdapter)得到它.

我忘了提到我正在使用Adam Speakman的FragmentStatePagerAdapter修复来解决我的问题.

////////////////////////////////////////////////// /// 问题部分 ///////////////////////////////////////////// /////////

说我遇到的问题是,我需要完全去除一些Fragments举行FragmentStatePagerAdapter.

我已经完成了POSITION_NONE它的修复,但旧片段似乎仍然完好无损.

施工

因为我的构造ViewPager是不寻常的,所以我被迫放置在我VerticalAdater伸展FragmentStatePagerAdapter的内部,它SparseArray可以容纳我所有的碎片.

public class VerticalAdapter extends FragmentStatePagerAdapter {

private SparseArray<Fragment> fragments = new SparseArray<Fragment>(); 
...

@Override
public Fragment getItem(int position) {
    return getFragmentForPosition(position);
}

@Override
public int getCount() {
    return fragments.size();
}
Run Code Online (Sandbox Code Playgroud)

问题

我已经制定了一个特殊的方法来清除Fragments我的所有内容FragmentStatePagerAdapter.它运作良好,但我无法摆脱的问题是清除ArrayList内部FragmentStatePagerAdapter.甚至尽管我明确SparseArrayArrayListFragmentStatePagerAdapter,我VerticalAdapter伸出仍抱着Fragments,我不希望有有.因此,当我创造新的时,Fragments它们具有旧的状态.

public void clearProgressUpTo(int progress) {
    boolean deleted = false;

    for (int i = fragments.size() - 1; i > 0; i--) {
        int key = fragments.keyAt(i);
        if (key != progress) {
            fragments.delete(key);
            deleted = true;
        } else {
            break;
        }
    }

    if (deleted)
        notifyDataSetChanged(); //prevents recursive call (and IllegalStateException: Recursive entry to executePendingTransactions)
}
Run Code Online (Sandbox Code Playgroud)

如果您需要更多信息/代码,请在评论中告诉我,我会尽量提供尽可能多的信息.

我不知道如何解决这个问题所以任何输入将不胜感激.

编辑

添加请求的代码.

private Fragment getFragmentForPosition(int position) {
    return fragments.get(getKeyForPosition(position));
}

public int getKeyForPosition(int position) {
    int key = 0;
    for (int i = 0; i < fragments.size(); i++) {
        key = fragments.keyAt(i);
        if (i == position) {
            return key;
        }
    }
    return key;
}
Run Code Online (Sandbox Code Playgroud)

Lei*_*Guo 7

您的问题不是由您使用SparseArray引起的.实际上,您遇到了FragmentStatePagerAdapter的错误.我花了一些时间阅读FragmentStatePagerAdapter,ViewPager和FragmentManagerImpl的源代码,然后找到了新片段具有旧片段状态的原因:

FragmentStatePagerAdapter在删除旧片段时保存它们的状态,如果稍后向适配器添加新片段,则保存的状态将传递到同一位置的新片段.

我搜索了这个问题并找到了解决方案,这是它的链接:http: //speakman.net.nz/blog/2014/02/20/a-bug-in-and-a-fix-for-the-way- fragmentstatepageradapter-手柄片段的恢复/

源代码可以在这里找到:https: //github.com/adamsp/FragmentStatePagerIssueExample/blob/master/app/src/main/java/com/example/fragmentstatepagerissueexample/app/FixedFragmentStatePagerAdapter.java

此解决方案的关键思想是重写FragmentStatePagerAdapter并使用String标记来标识适配器中的每个片段.因为每个片段都有不同的标记,所以很容易识别新的片段,然后不将已保存的状态传递给新的片段.

最后,感谢作为该解决方案作者的Adam Speakman.


Man*_*ani 7

FragmentStatePageAdapter 在销毁片段时保存片段的状态,以便后者在重新创建片段时,将应用已保存的状态.

片段状态存储在私有成员变量中.因此,我们无法扩展当前实现以添加删除已保存状态的功能.

我克隆了当前的FragmentStatePagerAdapter实现,并包含了已保存的状态删除功能.这是要点的参考.

   /**
     * Clear the saved state for the given fragment position.
     */
    public void removeSavedState(int position) {
        if(position < mSavedState.size()) {
            mSavedState.set(position, null);
        }
    }
Run Code Online (Sandbox Code Playgroud)

在您的clearProgressUpTo方法中,每当从稀疏数组中删除片段时,请调用此方法,该方法将清除该片段的已保存状态.