0

I have a ViewPager with 3 Fragments and my FragmentPagerAdapter:

private class test_pager extends FragmentPagerAdapter {
    public test_pager(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int i) {
        return fragments[i];
    }

    @Override
    public long getItemId(int position) {
        if (position == 1) {
            long res = fragments[position].hashCode()+fragment1_state.hashCode();
            Log.d(TAG, "getItemId for position 1: "+res);
            return res;
        } else
            return fragments[position].hashCode();
    }

    @Override
    public int getCount() {
        return fragments[2] == null ? 2 : 3;
    }

    @Override
    public int getItemPosition(Object object) {
        Fragment fragment = (Fragment) object;
        for (int i=0; i<3; i++)
            if (fragment.equals(fragments[i])){
                if (i==1) {
                    return 1; // not sure if that makes a difference
                }
                return POSITION_UNCHANGED;
            }

        return POSITION_NONE;
    }
}

In one of the page (#1), I keep changing the fragment to be displayed. The way I remove the old fragment is like this:

FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction().remove(old_fragment1).commit();

And then just changing the value of fragments[1]

I found that I cannot really add or replace the new one or it will complain the ViewPager is trying to add it too with another tag... (am I doing something wrong here?)

All the fragments I display have setRetainInstance(true); in their onCreate function.

My problem is that this usually works well for the first few replacement, but then when I try to reuse a fragment, sometimes (I have not really figured out the pattern, the same fragment may be displayed several times before this happens) it will only show a blank page.

Here is what I have found happened in the callback functions of my Fragment I am trying to display when the problem happens:

  • onAttach is called (but at that time, getView is still null)
  • onCreateView is not called (that's expected)
  • onViewStateRestored is not called (why not?)
  • onResume is not called (I really thought it would...)

If it changes anything, I am using the support package, my activity is a SherlockFragmentActivity

EDIT (to answer Marco's comment):

The fragments are instantiated in the onCreate function of the Activity, I fill an ArrayList with those fragments:

char_tests = new ArrayList<Fragment>(Arrays.asList(
            new FragmentOptionA(), new FragmentOptionB(), new FragmentOptionC()));

The I pick from that list to set fragments[1] (that's all done in the UI thread)

Matthieu
  • 16,103
  • 10
  • 59
  • 86
  • where are the fragments being created? – Marco RS Nov 15 '12 at 04:08
  • @Marco in the onCreate function of the Activity, I fill up an ArrayList of those fragments. I add the code in the question – Matthieu Nov 15 '12 at 04:37
  • The way your managing your fragments is a little strange. Checkout this question it seems to be related to your problem. http://stackoverflow.com/questions/7951730/viewpager-and-fragments-whats-the-right-way-to-store-fragments-state?rq=1 – Marco RS Nov 15 '12 at 05:05
  • @Marco I actually used the information in that question to implement onSaveInstanceState and support screen rotation properly. Can you say what part is strange to you? Also, it says to do a FragmentTransation.add() but as I put in the question, I am not able to do this since I am using a ViewPager – Matthieu Nov 15 '12 at 05:11
  • I usually do all the fragment instantiation inside the Fragment getItem(int i) method. After you build the fragment in that method the FragmentPagerAdapter seems to take over the adding/removing of the fragment. Are you dynamically trying change the number fragments based on some kind of condition? Or do you have the count logic as fragments[2] == null ? 2 : 3; because you notice that a fragment goes null? – Marco RS Nov 15 '12 at 05:17
  • Yeah, that fragments[2] is not always populated. That part does not seem to have any problem. Are you able to reuse the same Fragment several times or every time you want to change you create a new instance? – Matthieu Nov 15 '12 at 05:18

1 Answers1

0

I fixed this by changing test_pager to extends FragmentStatePagerAdapter instead.

I am still confused as to what PagerAdapter should be used depending on the usage. The only thing I can find in the documentation says that FragmentPagerAdapter is better for smaller number of pages that would be kept in memory and FragmentPagerStateAdapter better for a larger number of pages where they would be destroyed and save memory...

When trying to do (fancy?) things with Fragments, I found FragmentStatePagerAdapter is better when pages are removed and re-inserted like in this case. And FragmentPagerAdapter is better when pages move position (see bug 37990)

Matthieu
  • 16,103
  • 10
  • 59
  • 86