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

调用Firebase Cloud Firestore的add方法时Android应用冻结

解决Firestore add()方法导致应用冻结的问题

看起来你的Firestore数据插入操作卡住不动,而且没有任何报错,这种情况通常和对象序列化或者线程调用有关,我帮你梳理几个可能的排查方向:

1. 检查自定义对象是否符合Firestore序列化规范

Firestore在将自定义对象写入数据库时,严格遵循JavaBean规则,你需要确保:

  • Arma、Prop_Arma以及父类Equipo都包含公共的无参构造函数(如果自动生成的构造方法只带参数,会覆盖默认的无参构造,需要手动添加)
  • 所有需要存入Firestore的字段都有符合命名规范的getter方法:
    • 普通字段用getXxx()格式(比如getDano())
    • 布尔类型字段可以用isXxx()格式(比如isDano_var())
  • 避免字段出现循环引用(比如Arma引用Prop_Arma,而Prop_Arma又反向引用Arma,会导致序列化无限循环)

2. 排查是否有主线程阻塞操作

虽然add()是异步方法,但如果你的Arma或Prop_Arma类的getter/setter方法里包含阻塞主线程的逻辑(比如本地IO、网络请求),会导致序列化过程卡住。检查自动生成的方法里是否有意外添加的阻塞代码。

3. 验证Firestore实例与权限配置

  • 确认DBConnector中的db实例是通过FirebaseFirestore.getInstance()正确初始化的,没有重复初始化或配置错误
  • 检查Firebase控制台的Firestore安全规则,确保当前用户有写入目标集合的权限(权限问题通常会触发onFailureListener,但如果规则完全拒绝写入且没有错误回调,也可能导致卡住)

4. 用HashMap替换自定义对象做测试

临时将Arma对象替换为HashMap手动填充字段,调用add()方法测试:

public void addArmaOficial(Arma data) {
    if (data != null) {
        HashMap<String, Object> armaMap = new HashMap<>();
        armaMap.put("dano", data.getDano());
        armaMap.put("tipo_dano", data.getTipo_dano());
        armaMap.put("categoria_princ", data.getCategoria_princ());
        // 其他字段依次填入
        
        db.collection(Constants.COLLECTION_BASE)
          .document(Constants.COLLECTION_ARMAS)
          .collection(Constants.COLLECTION_OFIARM)
          .add(armaMap)
          .addOnSuccessListener(documentReference -> {
              Toast.makeText(ctx, R.string.accionexistosa, Toast.LENGTH_SHORT).show();
              ctx.finish();
          })
          .addOnCompleteListener(task -> 
              Toast.makeText(ctx, R.string.addarmaoficialtoast, Toast.LENGTH_SHORT).show()
          )
          .addOnFailureListener(e -> e.printStackTrace());
    } else {
        Toast.makeText(ctx, "Los datos son nulos", Toast.LENGTH_SHORT).show();
    }
}

如果这个测试能正常执行,说明问题肯定出在Arma或Prop_Arma的序列化逻辑上。

5. 添加日志追踪序列化流程

在Arma和Prop_Arma的所有getter方法中添加日志,查看序列化时是否能正常访问所有字段:

public String getDano() {
    Log.d("ArmaSerialize", "获取dano字段值: " + dano);
    return dano;
}

public boolean isDano_var() {
    Log.d("PropArmaSerialize", "获取dano_var字段值: " + dano_var);
    return dano_var;
}

如果日志停在某个字段上,说明该字段的getter方法存在问题。

另外,你代码中addOnSuccessListener和addOnCompleteListener都会触发Toast,成功时会连续弹出两个提示,这虽然不会导致冻结,但可以暂时注释掉ctx.finish()和Toast,排除UI操作带来的干扰。

内容的提问来源于stack exchange,提问作者Slifer Dragon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:25:39