从Dialog中删除RecyclerView项目不更新

时间:2017-02-14 03:30:24

标签: android android-recyclerview

我有一个简单的RecyclerView用于显示项目。目前,我可以使用以下内容从RecyclerView.Adapter成功删除项目。

private void removeItem(int pos) {    
    filteredDataSet.remove(pos);
    notifyItemRemoved(pos);
    notifyItemRangeChanged(pos, getItemCount());
}

我从onClick()中的ViewHolder函数调用它。动画有效,视图更新,一切正常。相当标准的RecyclerView。

但是,我想要做的是让用户通过Dialog验证项目删除。这是Dialog的基本设置(省略不必要的代码):

...

AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
builder.setTitle("Delete this item?");
builder.setView(layout);

final int itemPos = pos;

builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int id) {
        removeItem(itemPos);
    }
}); 

...

所以,我只是将方法调用移到Dialog的onClickListener

我遇到的问题是,当RecyclerView动画移除被移除的项目时,它会将其动画回到完全相同的位置,并且列表保持不变。就像它还在那里一样。

但是,如果我向下滚动,我会收到一个越界错误:

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position

这意味着它实际上并不存在,当它再次回到View中时,它就消失了。因此,它似乎是缓存而不是更新适配器或数据集。我读到它需要在主线程上调用,所以我修改了我的方法:

private void removeItem(int pos) {
final int itemPos = pos;

Handler handler = new Handler(Looper.getMainLooper());
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        filteredDataSet.remove(itemPos);
        notifyItemRemoved(itemPos);
        notifyItemRangeChanged(itemPos, getItemCount());
    }
};
handler.post(runnable);
}

它还没有用,我很茫然。我怀疑这是一个线程问题,但不知道从哪里开始。

2 个答案:

答案 0 :(得分:1)

通过使用回调来在从数据库中删除项目时触发removeItem()函数来解决此问题。显然,在实际从数据库中删除项目之前,会通知适配器。

我正在使用DBFlow执行查询,因此该解决方案仅适用于基于DBFlow的解决方案。这是从包含RecyclerView的视图中调用的:

public void deleteItem(int pos, long id) {
    DatabaseDefinition database = FlowManager.getDatabase(AppDatabase.class);

    //hold id to remove later
    final long tempId = id;
    final int tempPos = pos;

    final ItemModel currentItem = getItem(id);

    Transaction transaction = database.beginTransactionAsync(new ITransaction() {
        @Override
        public void execute(DatabaseWrapper databaseWrapper) {
            currentItem.delete();
        }
    }).success(new Transaction.Success() {
        @Override
        public void onSuccess(Transaction transaction) {
            mAdapter.removeItem(tempPos); //called here
        }
    }).error(new Transaction.Error() {
        @Override
        public void onError(Transaction transaction, Throwable error) {
            Log.d("delete error", "item not deleted");
        }
    }).build();

    transaction.execute();
}

答案 1 :(得分:0)

如果您从onClick班级ViewHolder移除,请使用getAdapterPosition()获取点击位置

如果此代码无效,您可以告诉onItemClick()

ViewHolder的内容