You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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();
            }
        }
    });
}

关键注意事项

  1. 移除无用变量:可以删除原代码中的stopDelete变量,因为现在不需要延迟删除逻辑。
  2. 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...
    }
    
  3. 优化数据库引用初始化:原代码中setDatabaseReference(account)在onBindViewHolder中重复调用,建议移到适配器构造函数中初始化一次,提升性能。

内容的提问来源于stack exchange,提问作者prabin chand

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 11:10:25