从Firebase Firestore拉取数据加载到RecyclerView时App崩溃如何解决
崩溃根因
日志已经明确指出问题核心:Firebase Firestore在将数据库文档反序列化映射为Item实体类对象时,检测到name属性存在大小写冲突的字段或者访问方法。
Firestore的实体类映射逻辑默认不区分大小写匹配字段名,触发该错误的常见场景:
Item类中同时声明了name和Name两个大小写不同的同名字段- 字段名与getter/setter命名不符合JavaBean规范,比如字段声明为
name但存在getNAme()这类大小写不匹配的访问方法 - 结合你提供的Firestore数据截图,数据库中的字段是首字母大写的
Name、Description,如果你的Item类字段命名和数据库字段大小写不匹配,同时没有显式指定映射关系,也可能触发该冲突。
修复方案
1. 修正Item实体类定义
首先确认Item类没有重复的同名字段,同时保证空构造方法存在(Firestore反序列化强制要求公共无参构造),有两种可选的映射方案:
方案A:字段名和Firestore字段完全对齐
public class Item { // 字段名和数据库里的首字母大写格式完全一致 private String Name; private String Description; // 必须保留公共无参构造 public Item() {} // 自定义构造方法 public Item(String name, String desc) { this.Name = name; this.Description = desc; } // getter/setter要和字段名匹配 public String getName() { return Name; } public void setName(String name) { Name = name; } public String getDescription() { return Description; } public void setDescription(String description) { Description = description; } }
方案B:用注解显式绑定字段映射
如果你想保持代码里的小驼峰命名规范,可以用@PropertyName注解显式指定对应Firestore的字段名:
import com.google.firebase.firestore.PropertyName; public class Item { @PropertyName("Name") // 显式绑定Firestore中的Name字段 private String name; @PropertyName("Description") // 显式绑定Firestore中的Description字段 private String description; public Item() {} public Item(String name, String description) { this.name = name; this.description = description; } // 正常写小驼峰的getter/setter即可 public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } }
2. 优化现有业务代码
你当前把adapter.notifyDataSetChanged()放在遍历循环内部,会导致每加一条数据就刷新一次列表,建议移到循环外部,同时记得关闭进度弹窗:
private void EventChangeListener() { db.collection("Foods") .addSnapshotListener(new EventListener<QuerySnapshot>() { @Override public void onEvent(@Nullable QuerySnapshot value, @Nullable FirebaseFirestoreException error) { if (error != null){ Toast.makeText(MainActivity.this, "Database Error " + error.getMessage(), Toast.LENGTH_SHORT).show(); if (pD.isShowing()) pD.dismiss(); return; } // 先清空旧数据避免重复加载 itemsList.clear(); for (DocumentChange dc : value.getDocumentChanges()){ if(dc.getType() == DocumentChange.Type.ADDED){ itemsList.add(dc.getDocument().toObject(Item.class)); } } // 遍历完成后统一刷新列表 adapter.notifyDataSetChanged(); // 关闭进度弹窗 if (pD.isShowing()) pD.dismiss(); } }); }
内容的提问来源于stack exchange,提问作者Velibor Simonovic
相关产品推荐
相关产品推荐

