android - FirebaseRecyclerAdapter with action mode to delete items -


i'm trying implement action mode delete items within firebaserecyclerview. weird thing deleted items not selected items. i'm think error in toogleselection method or removeitems method, i'm don't know is.

the adapter code:

public class newsadapter extends firebaserecycleradapter<noticia, noticiasviewholder> {      private int color;     private int selectedcolor;     private noticiasfragment fragment;     private final globals globals;     private actionmode actionmode;     private final simpledateformat dateformat = new simpledateformat("dd/mm/yyyy");     private sparseintarray selecteditems = new sparseintarray();      public newsadapter(noticiasfragment fragment, query ref) {          super(noticia.class, r.layout.list_item_noticia, noticiasviewholder.class, ref);         this.color = contextcompat.getcolor(fragment.getactivity(), r.color.background_card);         this.selectedcolor = contextcompat.getcolor(fragment.getactivity(), r.color.background_selected);         this.globals = (globals) fragment.getactivity().getapplicationcontext();         this.fragment = fragment;     }       @override     protected void populateviewholder(noticiasviewholder viewholder, final noticia model, final int position) {          viewholder.imageview.setimageurl(model.linkimg, globals.getimageloader());         viewholder.bindtonoticia(fragment.getactivity(), model, dateformat);          final databasereference noticiaref = getref(position);          viewholder.itemview.setonclicklistener(new view.onclicklistener() {             @override             public void onclick(view v) {                  if (getselecteditemcount()>0) {                      if (toggleselection(position)) {                         v.setbackgroundcolor(selectedcolor);                      } else {                         v.setbackgroundcolor(color);                         if (getselecteditemcount()==0 && actionmode!=null) {                             actionmode.finish();                         }                     }                     return;                 }                  if (!server.isonline(fragment.getactivity(), r.string.sem_conexao_noticia))                     return;                  intent = new intent(fragment.getactivity(), newsactivity.class);                 i.putextra("noticia", model);                 fragment.startactivity(i);             }         });          viewholder.itemview.setonlongclicklistener(new view.onlongclicklistener() {              @override             public boolean onlongclick(view v) {                  if (toggleselection(position)) {                     v.setbackgroundcolor(selectedcolor);                      if (actionmode != null)                         return true;                     toolbar toolbar = (toolbar) fragment.getactivity().findviewbyid(r.id.toolbar);                     actionmode = toolbar.startactionmode(mactionmodecallback);                     actionmode.settitle("1 selecionado");                  } else {                     v.setbackgroundcolor(color);                     if (getselecteditemcount() == 0 && actionmode != null) {                         actionmode.finish();                     }                 }                 return true;             }         });          if (selecteditems.get(position)!=0)             viewholder.itemview.setbackgroundcolor(selectedcolor);         else viewholder.itemview.setbackgroundcolor(color);      }       /* returns selected items count */     public int getselecteditemcount() {         return selecteditems.size();     }      /* select/unselect deletion */     public boolean toggleselection(int position) {         boolean b;         if (selecteditems.get(position)!=0) {             selecteditems.delete(position);             b = false;         }         else {             selecteditems.put(position, position);              b = true;         }         int n = getselecteditemcount();         if (n>0 && actionmode!=null) {             actionmode.settitle(string.valueof(n) + (n==1 ? " selecionado" : " selecionados"));         }         return b;     }      /* action delete selected items */     private void removeitems() {          string userid = fragment.getuid();          while (selecteditems.size()>0) {              int position = selecteditems.keyat(0);             databasereference noticiaref = getref(position);             fragment.mdatabase.child("user-news").child(userid).child(noticiaref.getkey()).removevalue();             selecteditems.removeat(0);         }     }      private actionmode.callback mactionmodecallback = new actionmode.callback() {          @override         public boolean oncreateactionmode(actionmode actionmode, menu menu) {              menuinflater inflater = actionmode.getmenuinflater();             inflater.inflate(r.menu.menu_delete_noticias, menu);              toolbar toolbar = (toolbar) fragment.getactivity().findviewbyid(r.id.toolbar);             toolbar.setbackgroundcolor(contextcompat.getcolor(fragment.getactivity(), r.color.accent2));              tablayout tablayout = (tablayout) fragment.getactivity().findviewbyid(r.id.sliding_tabs);             tablayout.setbackgroundcolor(contextcompat.getcolor(fragment.getactivity(), r.color.accent2));              final globals globals = (globals) fragment.getactivity().getapplicationcontext();             globals.isinactionmode = true;              ((mainactivity) fragment.getactivity()).updatepage(0);              if (build.version.sdk_int >= build.version_codes.lollipop) {                 window window = (fragment.getactivity()).getwindow();                 window.addflags(windowmanager.layoutparams.flag_draws_system_bar_backgrounds);                 window.setstatusbarcolor(contextcompat.getcolor(fragment.getactivity(), r.color.accent3));             }              return true;         }          @override         public boolean onprepareactionmode(actionmode actionmode, menu menu) {             return false;         }          @override         public boolean onactionitemclicked(final actionmode actionmode, menuitem menuitem) {              switch (menuitem.getitemid()) {                  case r.id.menu_main_delete_noticias:                      new sweetalertdialog(fragment.getcontext(), sweetalertdialog.warning_type)                             .settitletext(fragment.getresources().getstring(r.string.excluir_noticias))                             .setcontenttext(fragment.getresources().getstring(r.string.excluir_noticias_message))                             .setcanceltext(fragment.getresources().getstring(r.string.btn_nao_excluir))                             .setconfirmtext(fragment.getresources().getstring(r.string.btn_sim_excluir))                             .showcancelbutton(true)                             .setcancelclicklistener(new sweetalertdialog.onsweetclicklistener() {                                 @override                                 public void onclick(sweetalertdialog sdialog) {                                     actionmode.finish();                                     sdialog.cancel();                                 }                             })                             .setconfirmclicklistener(new sweetalertdialog.onsweetclicklistener() {                                 @override                                 public void onclick(sweetalertdialog sdialog) {                                      /* execute deletion */                                     removeitems();                                      actionmode.finish();                                     sdialog                                             .settitletext(fragment.getresources().getstring(r.string.noticias_excluidas))                                             .setcontenttext(fragment.getresources().getstring(r.string.noticias_excluidas_message))                                             .setconfirmtext(fragment.getresources().getstring(r.string.btn_ok))                                             .showcancelbutton(false)                                             .setconfirmclicklistener(null)                                             .changealerttype(sweetalertdialog.success_type);                                 }                             })                             .show();                     return true;                 default:                     return false;             }         }          @override         public void ondestroyactionmode(actionmode amode) {              fragment.getactivity().findviewbyid(r.id.action_mode_bar).setvisibility(view.invisible);              toolbar toolbar = (toolbar) fragment.getactivity().findviewbyid(r.id.toolbar);             toolbar.setbackgroundcolor(contextcompat.getcolor(fragment.getactivity(), r.color.primary));              tablayout tablayout = (tablayout) fragment.getactivity().findviewbyid(r.id.sliding_tabs);             tablayout.setbackgroundcolor(contextcompat.getcolor(fragment.getactivity(), r.color.primary));              final globals globals = (globals) fragment.getactivity().getapplicationcontext();             globals.isinactionmode = false;              ((mainactivity) fragment.getactivity()).selectpage(3);              if (build.version.sdk_int >= build.version_codes.lollipop) {                 window window = fragment.getactivity().getwindow();                 window.addflags(windowmanager.layoutparams.flag_draws_system_bar_backgrounds);                 window.setstatusbarcolor(contextcompat.getcolor(fragment.getactivity(), r.color.primarydark));             }             selecteditems.clear();             notifydatasetchanged();             actionmode = null;         }     }; } 

edit:

seems me index positions firebaserecyclerview not updated immediatly after remotions. realized that, if have 20 items , delete first 15 items, , if try delete new first one, following error:

08-01 21:12:35.816 10747-10747/com.doeal.doeal e/androidruntime: fatal exception: main                                                              process: com.doeal.doeal, pid: 10747                                                              java.lang.indexoutofboundsexception: invalid index 15, size 5                                                                  @ java.util.arraylist.throwindexoutofboundsexception(arraylist.java:255)                                                                  @ java.util.arraylist.get(arraylist.java:308)                                                                  @ com.firebase.ui.database.firebasearray.getitem(firebasearray.java:52)                                                                  @ com.firebase.ui.database.firebaserecycleradapter.getref(firebaserecycleradapter.java:150)                                                                  @ com.doeal.doeal.adapters.noticiasadapter.removeitems(noticiasadapter.java:187)                                                                  @ com.doeal.doeal.adapters.noticiasadapter.access$700(noticiasadapter.java:43)                                                                  @ com.doeal.doeal.adapters.noticiasadapter$4$1.onclick(noticiasadapter.java:248)                                                                  @ cn.pedant.sweetalert.sweetalertdialog.onclick(sweetalertdialog.java:372)                                                                  @ android.view.view.performclick(view.java:5201)                                                                  @ android.view.view$performclick.run(view.java:21163)                                                                  @ android.os.handler.handlecallback(handler.java:746)                                                                  @ android.os.handler.dispatchmessage(handler.java:95)                                                                  @ android.os.looper.loop(looper.java:148)                                                                  @ android.app.activitythread.main(activitythread.java:5443)                                                                  @ java.lang.reflect.method.invoke(native method)                                                                  @ com.android.internal.os.zygoteinit$methodandargscaller.run(zygoteinit.java:728)                                                                  @ com.android.internal.os.zygoteinit.main(zygoteinit.java:618) 

i tried execute notifydatasetchanged rebuild indexes, has no effect.

i found issue, that's mistake. in populateviewholder method, passing int position instead reference key onclicklistener , onlongclicklistener events. more relevant changes are:

private map<string, string> selecteditems = new hashmap<>(); 

...

viewholder.itemview.setonlongclicklistener(new view.onlongclicklistener() {         @override         public boolean onlongclick(view v) {             if (toggleselection(noticiaref.getkey())) {                 v.setbackgroundcolor(selectedcolor);                  if (actionmode != null)                     return true;                 toolbar toolbar = (toolbar) fragment.getactivity().findviewbyid(r.id.toolbar);                 actionmode = toolbar.startactionmode(mactionmodecallback);                 actionmode.settitle("1 selecionado");             } else {                 v.setbackgroundcolor(color);                 if (getselecteditemcount() == 0 && actionmode != null) {                     actionmode.finish();                 }             }             return true;         }     }); 

...

public boolean toggleselection(string key) {     boolean b;     if (selecteditems.get(key)!=null) {         selecteditems.remove(key);         b = false;     }     else {         selecteditems.put(key, key);         b = true;     }     int n = getselecteditemcount();     if (n>0 && actionmode!=null) {         actionmode.settitle(string.valueof(n) + (n==1 ? " selecionado" : " selecionados"));     }     return b; }  private void removeitems() {     string userid = fragment.getuid();      iterator iterator = selecteditems.keyset().iterator();     while(iterator.hasnext()) {         string key=(string) iterator.next();         fragment.mdatabase.child("user-news").child(userid).child(key).removevalue();     }     selecteditems.clear(); } 

Comments