Remove all fragments from ViewPager populated by FragmentStatePagerAdapter
Asked Answered
P

2

8

I have a ViewPager that I am populating with fragments(representing objects from arrayListOfObjects) using FragmentStatePagerAdapter. All works well:

            mMyFragmentPagerAdapter = new fragmentAdapter(getSupportFragmentManager(),orientation
            ,rePopulatedfireInfoList);
        mPager = (ViewPager)findViewById(R.id.fireInfoFragment_container);
        initButton();
        setTab();
        mPager.setAdapter(mMyFragmentPagerAdapter); 

The fragment adapter extends FragmentStatePagerAdapter.

From the primary activity I launch a dialog themed activity; where the user may add a new favourite location creating a new object which alters the arraylist of objects passed by the primary activity. This is the code for starting dialog activity; all works fine:

        Intent locationIntent = new Intent(afisController.this, locationActivity.class);
    locationIntent.putExtra("firesList", new fireInfoListWrapper(arrayListOfObjects));
    startActivityForResult(locationIntent,1);

The floating activity adds objects into arrayListOfObjects.

On the primary activity's onActivityResult I compare the arraListOfObjects I'm receiving with the one I sent; if different I want to completely remove the contents of the viewPager and recreate it with the new arrayListOfObjects. This is the onActivityResults:

     protected void onActivityResult(int requestCode, int resultCode,
            Intent data) {
 Toast.makeText(this, "Activity Results fired..." , 1500 ).show();
            if ((resultCode == 0) && (data != null)) { 
                Log.i("onActvityResult", "Inside resultCode check");   
                Bundle b = data.getExtras();
                if(b != null){
                    Log.i("onActvityResult", "not null");
                    returnedFireInfoList = (ArrayList<fireInfo>) data.getSerializableExtra("firesListResult"); 
                    Log.i("onActvityResult", "results Size: "+returnedFireInfoList.size());
                    if(returnedFireInfoList.size()>0){
                        Log.i("onActvityResult", "locationName: "+returnedFireInfoList.get(0).getLocationName());
                        //compare returnedFireInfoList and rePopulatedfireInfoList, if different; 
                        //add difference to rePopulatedfireInfoList and write back to file.
                        updateFireInfos(returnedFireInfoList, rePopulatedfireInfoList);
        if(returnedFireInfoList.size()!=rePopulatedfireInfoList.size()){
mMyFragmentPagerAdapter1 = new fragmentAdapter(getSupportFragmentManager(),orientation
                    ,returnedFireInfoList);
            mPager = (ViewPager)findViewById(R.id.fireInfoFragment_container); 
            Log.i("updateFireInfos", "fragmentsCount is"+mPager.getCurrentItem());
            fireInfoFragment fragment = 
                      (fireInfoFragment) getSupportFragmentManager().findFragmentById(R.id.fireInfoFragment_container);
//This is where the problem is, I don't want to remember what was already on the viewPager //called mPager before.
           //   mPager.removeAllViews();
            //mPager.setAdapter(null);
            mMyFragmentPagerAdapter1.notifyDataSetChanged();            
            mPager.setAdapter(mMyFragmentPagerAdapter1);               mMyFragmentPagerAdapter1.notifyDataSetChanged();                     
                    }                   
                }
            }        

This is the fragmentStateAdapter code:

public class fragmentAdapter extends FragmentStatePagerAdapter {

private FragmentManager fragmentManager;
 private FragmentTransaction mCurTransaction = null;
 private ArrayList<Fragment.SavedState> mSavedState = new ArrayList<Fragment.SavedState>();
 private ArrayList<Fragment> mFragments = new ArrayList<Fragment>();
 private Fragment mCurrentPrimaryItem = null;



public void restoreState(Parcelable state, ClassLoader loader) {
    //Need to only delete info from marked fragments (theoned that are stored on orientationchange
    //Currently redoing the entire call; resulting in delay due to server call
    //if(isLastOrientationPortrait != isPortrait){
    if(state != null){
        Bundle bundle1 = (Bundle) state;
        bundle1.setClassLoader(loader);
        Iterable<String> keys = bundle1.keySet();
        Log.i("restoreState", "containsKey FragmentStatePagerAdapter: "+keys);
        //android.support.v4.app.FragmentManager fragmentManager= fragmentAdapter.this.fragmentManager;
        android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 
        //if (fragmentTransaction == null) {
        //  Log.i("restoreState", "fragmentTransactionTest");

            fragmentTransaction = fragmentManager.beginTransaction();
       // }
        for (String key : keys) {
            if (key.startsWith("f")) {
                Fragment f = fragmentManager.getFragment(bundle1,
                        key);
                fragmentTransaction.remove(f);
                fragmentTransaction.commit();
            }
            }
        }
    //}       
    }


@Override
public int getItemPosition(Object object) {
    // TODO Auto-generated method stub
    //return super.getItemPosition(object);
    return fragmentAdapter.POSITION_NONE;
}


public fragmentAdapter(android.support.v4.app.FragmentManager fragmentManager,String orientation,
         ArrayList<fireInfo> fireInfoList) {
     super(fragmentManager);
     this.orientation = orientation;
     this.fireInfoList = fireInfoList;
     this.numItems = fireInfoList.size();
     this.fragmentManager=fragmentManager;
 }
 ArrayList<fireInfo> fireInfoList;
 String orientation;
 int numItems;


@Override
 public int getCount() {
     Log.i("numItems", "is: "+fireInfoList.size());
     return numItems;
 }

@Override
public Fragment getItem(int arg0) {
    Log.i("fragmentAdapterIndex", "is: "+arg0);
    return fireInfoFragment.newInstance(orientation, fireInfoList.get(arg0));
}    

}

Problem: But the new ArrayListOfObjects is added alongside the old one before I fired the startActivityFor results.

How do I force the viewPager to forget it old content? basically reset the viewPager adapter with this newArrayListofObjects using my fragmentStateAdapter?

Penology answered 15/5, 2013 at 8:41 Comment(0)
S
53

I guess the problem is in the fact that old fragments still reside in FragmentManager you use for your adapter. If this is the case all you have to do is remove all old fragments from the fragment manager.

So basically just execute the following code in the constructor of your adapter:

public fragmentAdapter(FragmentManager fragmentManager, String orientation, ArrayList<fireInfo> list) {
    super(fragmentManager);
    if (fragmentManager.getFragments() != null) {
        fragmentManager.getFragments().clear();
    }
    //... your other code here
}

This line of code is unnecessary:

mMyFragmentPagerAdapter1.notifyDataSetChanged();     

EDIT: It may be more correct to remove your fragments using FragmentTransaction:

    List<Fragment> fragments = fragmentManager.getFragments();
    if (fragments != null) {
        FragmentTransaction ft = fragmentManager.beginTransaction();
        for (Fragment f : fragments) {
            //You can perform additional check to remove some (not all) fragments:
            if (f instanceof AddedByCurrentPagerAdapterFragment) { 
                ft.remove(f);
            }
        }
        ft.commitAllowingStateLoss();
    }

This will take some time for FragmentTransaction to be (asynchronously) performed.

Scharaga answered 19/11, 2013 at 10:4 Comment(7)
What happens when you want to keep other fragments managed by the same FragmentManager but only want to remove the fragments created by this FragmentPagerAdapter?Dwell
@Dwell See EDIT sectionScharaga
fragmentManager.getFragments() is not a public function: #42572749Premise
@appdeveloper27 It was until recently. Currently I am not sure what to replace it with. What I can advice is to use older version of support library where getFragments() method was still publicScharaga
fragmentManager.getFragments() returns list which (in my case at least) isn't null whereas it's size is 0. Hence, it's better to check for the number of the fragments the list returned by fragmentManager.getFragments() is having instead of checking it for nullity.Contusion
fragmentManager.getFragments().clear(); don't work, fragmentManager.getFragments() return a copied FragmentList.Uranus
This doesn´t work anymore.Downswing
P
0

All I needed to do was to re-assign the FragmentStatePagerAdapter.

This has been in place as can be seen in onActivityResult but what was masking the correct behaviour was my viewPager page indicator it was incrementing the pages e.g. if I had 2 pages on the viewPager and call the child actvity which will add one object on the arrayListOfObjects; the viewPager page indicator would show that I now have 2 plus three pages (5).

I had to reset the viewPage indicator in onActivityResult to have it determined by this new arrayListOfObjects just returned by the floating activity.

Penology answered 16/5, 2013 at 15:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.