如何在FirebaseRecyclerAdapter中实现基于Snackbar的撤销功能?
解决方案
要实现点击删除后条目立即消失、点击撤销后恢复的功能,核心思路是立即从Firebase删除条目让列表同步更新,同时缓存被删条目,在撤销时重新写入Firebase。以下是修改后的代码和关键说明:
修改后的删除逻辑代码
在onMenuItemClick的Delete分支中替换原有代码:
else if (menuItem.getTitle().equals("Delete")) { // 获取当前条目的适配器位置和Firebase键值 int adapterPosition = holder.getAdapterPosition(); if (adapterPosition == RecyclerView.NO_POSITION) { return true; } String itemKey = getRef(adapterPosition).getKey(); if (itemKey == null) { return true; } // 缓存被删除的条目数据 ExpenseModel deletedItem = model; // 立即从Firebase删除条目,列表会自动同步隐藏该条目 databaseReference.child(itemKey).removeValue().addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if (task.isSuccessful()) { int timeSnackBar = 5000; // 显示撤销提示 Snackbar snackbar = Snackbar.make(view, "条目已删除", Snackbar.LENGTH_LONG) .setAction("撤销", new View.OnClickListener() { @Override public void onClick(View view) { // 点击撤销时,将缓存的条目重新写入Firebase,列表自动恢复显示 databaseReference.child(itemKey).setValue(deletedItem) .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if (task.isSuccessful()) { Toast.makeText(context, "条目已恢复", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(context, "恢复失败,请检查网络", Toast.LENGTH_SHORT).show(); } } }); } }).setDuration(timeSnackBar); Snackbar.SnackbarLayout snackbarLayout = (Snackbar.SnackbarLayout) snackbar.getView(); snackbarLayout.setPadding(0, 0, 0, 0); snackbar.show(); } else { Toast.makeText(context, "删除失败,请检查网络", Toast.LENGTH_SHORT).show(); } } }); }
关键注意事项
- 移除无用变量:可以删除原代码中的
stopDelete变量,因为现在不需要延迟删除逻辑。 - ExpenseModel类要求:确保你的
ExpenseModel类包含无参构造函数,并且所有字段是public或拥有getter/setter方法,否则Firebase无法正常序列化/反序列化对象:public class ExpenseModel { public String description; public String amount; public String time; public String exType; // Firebase必需的无参构造函数 public ExpenseModel() {} // 带参构造函数 public ExpenseModel(String description, String amount, String time, String exType) { this.description = description; this.amount = amount; this.time = time; this.exType = exType; } // 可选:getter/setter方法 public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } // 其他字段的getter/setter... } - 优化数据库引用初始化:原代码中
setDatabaseReference(account)在onBindViewHolder中重复调用,建议移到适配器构造函数中初始化一次,提升性能。
内容的提问来源于stack exchange,提问作者prabin chand
相关产品推荐
相关产品推荐

