Android开发:从Firebase查询数据后无法初始化PGCharacter对象
搞定Cloud FireStore查询PGCharacter对象的问题
嘿,我来帮你解决这个FireStore查询的问题!你正在开发类似Tanoth/OGame的复古安卓游戏,已经通过Intent传了角色名称,现在想从FireStore里捞对应的PGCharacter对象对吧?下面是一步步的实用方案,都是结合Android+FireStore的实际开发经验来的:
1. 先把Intent传的角色名稳稳拿到手
首先在目标Activity的onCreate里,先把传递过来的角色名称正确取出来,一定要做空值校验,不然后续查询容易踩坑:
// 从Intent获取角色名,这里的KEY要和登录页跳转时用的完全一致哦 String characterName = getIntent().getStringExtra("CHARACTER_NAME"); // 先检查有没有拿到有效数据 if (characterName == null || characterName.trim().isEmpty()) { Toast.makeText(this, "角色名称不能为空哦", Toast.LENGTH_SHORT).show(); finish(); // 直接返回登录页或者做其他兜底处理 return; }
2. 确认FireStore和集合引用初始化正确
你说已经在onCreate里初始化了数据库和集合,这里再给你贴个标准写法,确保没出错:
// 初始化FireStore实例 FirebaseFirestore db = FirebaseFirestore.getInstance(); // 获取存储角色的集合引用,假设你的集合名叫"pg_characters",改成你自己的就行 CollectionReference charactersCollection = db.collection("pg_characters");
3. 执行查询并把结果转成PGCharacter对象
接下来就是核心的查询环节了。FireStore的查询是异步的,所以要通过回调处理结果,而且你的PGCharacter类得符合FireStore的序列化要求,先给你理清楚:
先把PGCharacter类调整成FireStore能识别的样子
FireStore要把文档转成实体类,需要满足几个小要求:
- 必须有无参构造函数(FireStore反射用的,不能省)
- 所有字段要有对应的getter和setter
- 字段名要和FireStore文档里的字段名一致(如果不一样可以用
@PropertyName注解映射)
举个例子,你的PGCharacter类可以这么写:
public class PGCharacter { private String name; private int level; private long credits; // 你的其他角色属性... // 必须要有这个无参构造函数 public PGCharacter() {} // 带参构造函数(可选,方便你创建角色对象) public PGCharacter(String name, int level, long credits) { this.name = name; this.level = level; this.credits = credits; } // 所有字段的getter和setter,一个都不能少哦 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } public long getCredits() { return credits; } public void setCredits(long credits) { this.credits = credits; } }
然后执行查询逻辑
你已经在类开头声明了PGCharacter变量,现在就可以在回调里给它赋值了:
// 你已经声明的类级别的PGCharacter变量 private PGCharacter currentCharacter; // 在onCreate里执行查询 charactersCollection.whereEqualTo("name", characterName) // 按角色名精确匹配 .get() .addOnCompleteListener(task -> { if (task.isSuccessful()) { // 因为角色名应该是唯一的,所以遍历结果只会拿到一个文档 for (QueryDocumentSnapshot doc : task.getResult()) { // 把FireStore文档直接转成PGCharacter对象 currentCharacter = doc.toObject(PGCharacter.class); // 这里就可以用currentCharacter做后续操作啦,比如更新游戏UI loadCharacterDataToUI(currentCharacter); } // 如果没找到对应的角色 if (currentCharacter == null) { Toast.makeText(this, "没找到这个角色的信息哦", Toast.LENGTH_SHORT).show(); } } else { // 查询失败了,处理错误 Log.d("FireStoreError", "查询角色失败: ", task.getException()); Toast.makeText(this, "查询角色信息失败,请稍后重试", Toast.LENGTH_SHORT).show(); } });
4. 几个要注意的小细节
- 角色名唯一性:一定要确保FireStore集合里的角色名是唯一的,不然可能查到多个结果。你可以去FireStore控制台给
name字段创建唯一索引,从根源避免重复角色。 - 异步回调的坑:FireStore查询是异步的,所以千万不要在查询代码之后直接用
currentCharacter,一定要在addOnCompleteListener的回调里处理,不然会拿到空值哦。 - 安全规则:记得配置FireStore的安全规则,比如只允许用户查询自己的角色,避免别人随便查你的游戏数据。
内容的提问来源于stack exchange,提问作者Alberto Calabrese
相关产品推荐
相关产品推荐

