1

I'm trying to replace fragments in ViewPager, but I'm facing a problem I've been unable to fix for several days. The relevant code and specific problem, as I understand it, are described below:

public class ViewPageAdapter extends FragmentStatePagerAdapter {
int mNumOfTabs;
FragmentManager mFragmentManager;
Fragment0 currentFragment0;
Fragment1 currentFragment1;
Fragment2 currentFragment2;
boolean getItemNeverCalled = true;

public ViewPageAdapter(FragmentManager fm, int numOfTabs){
    super(fm);
    mFragmentManager = fm;
    this.mNumOfTabs = numOfTabs;
}

@Override
public Fragment getItem(int position){
    switch (position){
        case 0:
            if(currentFragment0 == null){
                Fragment0 tab0 = new Fragment0();
                currentFragment0 = tab0;
                return currentFragment0;

            }
            else {
                mFragmentManager.beginTransaction().remove(currentFragment0).commit();
                int value = selectedPlant.getMoistureFrag().getStat().getOptimalLevel();
                currentFragment0 = Fragment0.newInstance(key0, value);
                notifyDataSetChanged(); // calls getItem(0).

                return currentFragment0;
            }
        case 1:
            if(currentFragment1 == null){
                LightFragment tab1 = new Fragment1();
                currentFragment1 = tab1;

                return currentFragment1;
            }
            else {
                mFragmentManager.beginTransaction().remove(currentFragment1).commit();
                int value = selectedPlant.getLightFrag().getStat().getOptimalLevel();
                currentFragment1 = currentFragment1.newInstance(key1, value);
                notifyDataSetChanged();

                return currentFragment1;
            }
        case 2:
            if(currentFragment2 == null){
                Fragment2 tab2 = new Fragment2();
                currentFragment2 = tab2;

                return currentFragment2;
            }
            else {
                mFragmentManager.beginTransaction().remove(currentFragment2).commit();
                int value = selectedPlant.getTempFrag().getStat().getOptimalLevel();
                currentFragment2 =  Fragment2.newInstance(key2, value);
                notifyDataSetChanged();

                return currentFragment2;
            }

        default:
            return null;
    }
}



@Override
public int getCount(){
    return mNumOfTabs;
}

@Override
public int getItemPosition(Object object){
            return POSITION_NONE;
}

I've overriden the getItemPosition(Object object) method to always return POSITION_NONE, and called notifyDataSetChanged() when appropriate (I think). What ends up happening is that notifyDataSetChanged() calls getItem(0), which calls `notifyDataSethanged()... and so on. This causes a TransactionTooLargeException and crashes the app.

Just to give some background to the if/else statements in each case: the if is meant to load a blank Moisture/Light/etc Fragment onto the screen. This is intended to happen on start-up. The else statement is executed when a user presses on a item in the navigation drawer, which has some data. This data is then extracted and set as arguments for the fragments that are meant to replace the initial blank fragment.

I genuinely appreciate any help. This problem is driving me crazy.

Miki P
  • 601
  • 1
  • 9
  • 21

1 Answers1

1

Why in the world are you recreating fragments, when you can just update the old ones?
Also, when you are calling notifyDataSetChanged during getItem then you are forcing a new call to getItem which will force a new call...so you are actually creating a circular call!
Since you are always keeping the same fragment class in each position, and you are holding on to the fragment, then you should not replace fragment. Just change the fragment you are holding to show the new values. The code you are using is only needed if you want to change different fragment classes for position.

lionscribe
  • 2,917
  • 1
  • 12
  • 17
  • Was having some troubles initially (before I knew that method existed), so I followed http://stackoverflow.com/questions/7723964/replace-fragment-inside-a-viewpager and several other posts that suggested the same thing. I will let you know how it goes. – Miki P Aug 10 '16 at 04:36
  • BTW, since you are always keeping the same fragment class in each position, and you are holding on to the fragment, then you should be redesigning your code. You should not replace fragment, just change the fragment you are holding to show the new values. The code you are using is only needed if you want to change different fragment classes for position. – lionscribe Aug 10 '16 at 04:41
  • Ok, I see. Does that mean I shouldn't use the getItem method past the initialization of the tabs on start-up? – Miki P Aug 10 '16 at 04:54
  • Correct. Why should they be replaced if they can just be updated. I will be editing my answer above (if I can). – lionscribe Aug 10 '16 at 04:56
  • Ok I see. If you are asking me for permission, you have it lol. – Miki P Aug 10 '16 at 04:58
  • Good lord... It works. I was under the impression that I have to call getItem() to get the tabs to change in any way. Thank you!! – Miki P Aug 10 '16 at 05:07
  • You're welcome. I wish all OPs would be so appreciative. – lionscribe Aug 10 '16 at 05:09
  • Also, don't forget to remove the `getItemPosition` function. No need, and will cause problems. – lionscribe Aug 10 '16 at 05:12
  • Ok, I did. Thank you again, you were a big help:) – Miki P Aug 10 '16 at 05:16