Ich versuche, einen Aktionsmodus zum Löschen von Elementen in FirebaseRecyclerView zu implementieren. Das Seltsame ist, dass manchmal die gelöschten Objekte nicht die ausgewählten Objekte sind. Ich denke, dass der Fehler in ToogleSelection-Methode oder RemoveItems-Methode ist, aber ich weiß nicht, was es ist.FirebaseRecyclerAdapter mit Aktionsmodus zum Löschen von Elementen
Der 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 i = 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 for 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 to 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:
mir scheint, dass die Indexpositionen von FirebaseRecyclerView nicht sofort nach dem remotions aktualisiert. Ich erkannte, dass, wenn ich 20 Produkte haben und die ersten 15 Elemente löschen, und wenn ich versuche, die neue erste zu löschen, erhalte ich folgende Fehlermeldung:
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 is 5
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at com.firebase.ui.database.FirebaseArray.getItem(FirebaseArray.java:52)
at com.firebase.ui.database.FirebaseRecyclerAdapter.getRef(FirebaseRecyclerAdapter.java:150)
at com.doeal.doeal.adapters.NoticiasAdapter.removeItems(NoticiasAdapter.java:187)
at com.doeal.doeal.adapters.NoticiasAdapter.access$700(NoticiasAdapter.java:43)
at com.doeal.doeal.adapters.NoticiasAdapter$4$1.onClick(NoticiasAdapter.java:248)
at cn.pedant.SweetAlert.SweetAlertDialog.onClick(SweetAlertDialog.java:372)
at android.view.View.performClick(View.java:5201)
at android.view.View$PerformClick.run(View.java:21163)
at android.os.Handler.handleCallback(Handler.java:746)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5443)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
ich NotifyDatasetChanged versucht ausführen, die Indizes neu zu erstellen, hat aber keine Wirkung.