RecyclerView ItemTouchHelper getAdapterPosition() возвращает неправильное значение при быстром пролистывании
У меня проблема с RecyclerView + Swipe для удаления + отмены с помощью снэк-бара. Всякий раз, когда я пытаюсь быстро пролистать 3+ предметов, чтобы удалить их, viewHolder.getAdapterPosition();
возвращает неправильное значение. Похоже, он не может реагировать так быстро.
RecyclerView list Пример:
- Test1
- Test2
- Test3
- Test4
Итак, если я быстро проведу пальцем по Test3, Test2, а затем Test1 viewHolder.getAdapterPosition();
возвращает позиции 2, 2 и затем 0. Правильный возврат должен быть 2, 1, а затем 0.
Для двух элементов все ведет себя нормально, возвращает 2, а затем 1.
Примечание: последняя позиция всегда возвращается через 2 секунды, потому что тайм-бар истекает, а затем элемент удаляется. Закусочные, которые показываются раньше, закрываются, как только следующий предмет удаляется.
Есть идеи как решить это? Я пытался понять это в течение нескольких часов.
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(final RecyclerView.ViewHolder viewHolder, int swipeDir) {
final int position = viewHolder.getAdapterPosition();
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
rusure = Snackbar.make(fab, getResources().getString(R.string.rule_deleted), Snackbar.LENGTH_SHORT).addCallback(new Snackbar.Callback() {
@Override
public void onDismissed(Snackbar snackbar, int event) {
switch(event) {
case Snackbar.Callback.DISMISS_EVENT_ACTION:
rulesAdapter.notifyDataSetChanged();
break;
case Snackbar.Callback.DISMISS_EVENT_TIMEOUT:
case Snackbar.Callback.DISMISS_EVENT_CONSECUTIVE:
case Snackbar.Callback.DISMISS_EVENT_MANUAL:
Log.d("test", Integer.toString(position));
if(position!=-1 && position<arrayList.size()){
// Define 'where' part of query.
String selection = DatabaseTablesColums.FeedEntry._ID + " LIKE ?";
// Specify arguments in placeholder order.
String[] selectionArgs = {Integer.toString(arrayList.get(position).getId())};
// Issue SQL statement.
arrayList.remove(position);
rulesAdapter.notifyItemRemoved(position);
rulesAdapter.notifyItemRangeChanged(position, rulesAdapter.getItemCount());
db.delete(DatabaseTablesColums.FeedEntry.TABLE_NAME, selection, selectionArgs);
// Remove item from backing list here
}
break;
}
}
@Override
public void onShown(Snackbar snackbar) {
}
}).setAction(getResources().getString(R.string.undo), new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
rusure.show();
}
});
itemTouchHelper.attachToRecyclerView(recyclerView);
1 ответ
Похоже, вы удаляете элемент из резервного хранилища данных, в вашем случае это arrayList
и уведомляет адаптер только после отклонения SnackBar.
Таким образом, если вы проведете пальцем по следующему элементу до того, как будет снят первый снэк-бар, адаптер RecyclerView не поймет, что первый элемент был удален из адаптера. Так что это дает вам неправильную позицию.
Вы должны удалить элемент из резервного хранилища данных (arrayList) и вызвать notifyItemRemoved()
как только вы проведете предмет, а не обновите его после того, как снэк-бар исчезнет.
Вы можете обновить базу данных только после закрытия SnackBar.