Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
173 views
in Technique[技术] by (71.8m points)

android - Removing fragments from FragmentStatePagerAdapter

UPDATE

After some major fighting with this problem and help from SO users I managed to solve it. This is how my clearProgressUpTo looks like now.

    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);
    }

}

The reason why I am doing it after notifyDataSetChanged is because the initiateItem was filling my mSavedState once again. And I am sure that after notifying my adapter does not hold any of these Fragments.

Also if you want to do it like that change your mSaveState to protected so you will be able to get it from the extending class (in my case VerticalAdapter).

I forgot to mention that I am using FragmentStatePagerAdapter fix by Adam Speakman to solve my problem.

/////////////////////////////////////////////////////QUESTION PART//////////////////////////////////////////////////////

the problem that I'm having is that I need to remove completely some of Fragments held in FragmentStatePagerAdapter.

I have already done the POSITION_NONE fix on it but the old fragments seems to still remain intact.

CONSTRUCTION

Because the construction of my ViewPager is unusual I was forced to place Inside my VerticalAdater extending FragmentStatePagerAdapter a SparseArray that holds all my fragments.

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();
}

PROBLEM

I have made a special method responsible for clearing all the Fragments up to some point in my FragmentStatePagerAdapter. Its working well but the problem I cant get rid of is clearing the ArrayList inside FragmentStatePagerAdapter. Even tho I clear the SparseArray, the ArrayList of FragmentStatePagerAdapter that my VerticalAdapter extends is still holding the Fragments that I don't want to have there. Because of that when I create new Fragments they have the state of the old ones.

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)
}

If you need more info/code please tell me in the comments I will try to provide as much info as I can.

I have no idea how to fix this problem so any input would be appreciated.

EDIT

Adding requested code.

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;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your problem is not caused by your use of SparseArray. In fact, you meet a bug of the FragmentStatePagerAdapter. I spent some time reading the source code of FragmentStatePagerAdapter, ViewPager and FragmentManagerImpl and then found the reason why your new fragments have the state of old ones:

The FragmentStatePagerAdapter save the sate of your old fragments when it remove them, and if you add new fragments to you adapter later, the saved state will be passed to your new fragment at the same location.

I googled this problem and find a solution, here is its link: http://speakman.net.nz/blog/2014/02/20/a-bug-in-and-a-fix-for-the-way-fragmentstatepageradapter-handles-fragment-restoration/

The source code can be found here: https://github.com/adamsp/FragmentStatePagerIssueExample/blob/master/app/src/main/java/com/example/fragmentstatepagerissueexample/app/FixedFragmentStatePagerAdapter.java

The key idea of this solution is to rewrite the FragmentStatePagerAdapter and use a String tag to identify each fragment in the adapter. Because each fragment has a different tag, it is easy to identify a new fragment, then don't pass a saved state to a new Fragment.

Finally, say thanks to Adam Speakman who is the author of that solution.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...