简体   繁体   中英

How to avoid duplicates in ArrayList containing Fragments

I'm working on an app that has a ViewPager with dynamic Fragment insertion,depending on what the user presses on witch Fragment.

I've been digging for two days for finding a way to avoid duplicate Fragment creating in said ViewPager.

First option, i tried:

ArrayList.contains(fragment) 

and always returned false. I searched and it turns out i have to override the equals and hashCode methods in the Fragment class, but hashCode is declared final, so no luck there.

Second option, why not using a LinkedHashMap ? I cant find a way to get the elements from it like you would on an ArrayList.get(index) kinda way, so i tried:

Fragment[] fragments =  LinkedHashMap.toArray() 

and iterate on that, but i cant cast from Object[] to Fragment[] , i don't know why since it inherits from it.

Third option,

public boolean verifyDuplicates(Fragment f){
   for(Fragment fragment: mFragments){
      if(f.getClass().equals(fragment.getClass()) return true;

   }
}

But i get a " unable to resolve symbol getClass() "..

Fourth option, getting the Fragment id and if it matches to any of the ids of the existing Fragment inside the ArrayList, then don't add it. Well for some reason, if i create say a FragmentA two a first time and add it to the ArrayList, and then create a second FragmentA and compare their ids, they are completely different, so it gets added. However, if i create a third FragmentA, its id matches to second FragmentA id, so i end up with two repeated FragmentA.(first and second)

Anyway, here is the code... Is there a way to identify the fragments? a way to make sure you don't have duplicates?

Thanks

Method on charge of inserting new Fragment:

private void nextView(View v){


    Log.d("onViewSwipe", String.valueOf(v.getId()));
    Fragment f = getNextFragment(v.getId());


    if(f == null){
        Log.e("FRAGMENT", "NULL");
    }
    else{
        Log.e("FRAGMENT", f.toString());
    }

    /*Verify that that page doesnt already exist*/
    if(!compareDuplicates(f)) {
        Log.d("FRAGMENT", "DOESNT EXISTS");
        mFragments.add(f);
        mViewPagerAdapter.notifyDataSetChanged();
        mViewPager.setCurrentItem(mFragments.size()-1);
    }



} 

Method comparing them:

 private boolean compareDuplicates(Fragment f){


    for(Fragment fragment: mFragments){

        int idF = f.getId(); //for debugging
        int idFrag = fragment.getId(); //for debugging

        if(f.getId() == fragment.getId()){
            return true;
        }

    }

    return false;

}

ViewPagerAdapter:

public class ViewPagerAdapter extends FragmentStatePagerAdapter {

ArrayList<Fragment> mFragments;
Context context;


public ViewPagerAdapter(FragmentManager fm, ArrayList<Fragment> mFragments, Context context) {
    super(fm);
    this.mFragments = mFragments;
    this.context = context;
}

public void setmFragments(ArrayList<Fragment> mFragments) {
    this.mFragments = mFragments;
}

@Override
public Fragment getItem(int position) {
    return mFragments.get(position);
}

@Override
public int getCount() {
    return (mFragments != null) ? mFragments.size():0;
}

Additional Info:

The host activity handles a callback that is the same for every fragment, invoked by the fragment containing the button or element that triggers the new fragment insertion. That callback calls to nextView(v)

I am not sure if this is the best solution although it works.

public class deleteDup<T> {
      public ArrayList<T> deleteDup(ArrayList<T> al) {

        ArrayList<T> alNew=new ArrayList<>();
        HashSet<T> set = new HashSet<>(alNew);
          for (T al1 : al) {
              if (!set.contains(al1)) {
                  alNew.add(al1);
                  set.add(al1);
              }
          }
         return alNew;   
        }  

      public static void main(String[] args){
          ArrayList<String> list = new ArrayList<>();
            list.add("A");
            list.add("B");
            list.add("A");
            deleteDup<String> dD=new deleteDup<>();
            System.out.println(dD.deleteDup(list));
      }
}

The first option should make it work. There's no need to implements hashCode nor equals .

Following is a sample to use ArrayList.contains(obj)

    ArrayList<Fragment>  list = new ArrayList<Fragment>();
    Fragment f1 = new Fragment();
    Fragment f2 = new Fragment();
    list.add(f1);
    if(!list.contains(f2)){
        Log.d("Main", "contains no f2");
    }
    if(list.contains(f1)){
        Log.d("Main", "contains f1");
    }

Both of the log would print.

So you may change compareDuplicates like following,

private boolean compareDuplicates(Fragment f){
    return mFragments.contains(f);
}

Turns out that the:

getClass() 

method did work after doing a File -> Invalidate Caches / Restart and clean + rebuild.

Android Studio bug i guess..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM