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

Java如何从Firebase Firestore的Map类型字段中读取存储数据

Cloud Firestore Map类型字段读取问题(Java Android)

需求说明

需要检索Cloud Firestore中Map类型字段的数据,具体需求为从All Comments字段中获取字符串类型的Comment值,将其展示在TextView控件中,开发使用语言为Java,对应数据库结构参考截图:
数据库结构截图

已尝试方案

方案1:写入根集合后读取,应用崩溃

写入代码

Map<String,String> allComments=new HashMap<String,String>();
String commentContent=commentboxedittext.getText().toString();
allComments.put("Movie Name",name);
allComments.put("Comment",commentContent);
firebaseFirestore.collection("All Comments").document("MovieComments").set(allComments, SetOptions.merge());  

读取代码

DocumentReference docRef = firebaseFirestore.collection("All Comments").document("MovieComments");
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
    @Override
    public void onComplete(@NonNull Task<DocumentSnapshot> task) {
        if (task.isSuccessful()) {
            DocumentSnapshot document = task.getResult();
            if (document.exists()) {
                Map<String, Object> m=document.getData();
                userComment=m.get("Comment").toString();
                mName=m.get("Movie Name").toString();
            } else {
                Toast.makeText(MovieDetails.this, "No Such Document", Toast.LENGTH_SHORT).show();
            }
        } else {
            Toast.makeText(MovieDetails.this, "Error", Toast.LENGTH_SHORT).show();
        }
    }
});  

执行上述检索代码后应用发生崩溃。


方案2:写入用户文档嵌套字段,写入正常但无对应读取逻辑

该写入方式可正常完成数据存储,但不清楚该嵌套结构下的检索方法,写入代码如下:

Map<String,String> allComments=new HashMap<String,String>();
Map<String, Object> user=new HashMap<String,Object>();
userID=firebaseAuth.getCurrentUser().getUid();
userReference=firebaseFirestore.collection("Users ").document(userID);
String commentContent=commentboxedittext.getText().toString();
allComments.put("Movie Name",name);
allComments.put("Comment",commentContent);
user.put("All Comments",allComments);
userReference.set(user, SetOptions.merge()).addOnSuccessListener(new OnSuccessListener<Void>() {
    @Override
    public void onSuccess(Void unused) {
        Toast.makeText(MovieDetails.this, "Comment Added", Toast.LENGTH_SHORT).show();
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        if(e instanceof FirebaseNetworkException)
            Toast.makeText(MovieDetails.this, "No Internet Connection", Toast.LENGTH_SHORT).show();
        Toast.makeText(MovieDetails.this, "Values Not Stored", Toast.LENGTH_SHORT).show();
    }
});

解决方案

方案1崩溃原因

  • 未做非空判断:m.get("Comment")如果取到null,直接调用toString()会触发空指针异常
  • 路径不匹配:如果实际数据是嵌套存储在用户文档下,读取根集合All Comments下的文档自然拿不到对应字段,返回null触发崩溃

两种存储结构对应的正确读取代码

情况1:数据存储在根集合All Comments/MovieComments下(对应第一种写入逻辑)

读取时直接调用SDK提供的字段取值方法,增加非空判断即可:

DocumentReference docRef = firebaseFirestore.collection("All Comments").document("MovieComments");
docRef.get().addOnCompleteListener(task -> {
    if (task.isSuccessful()) {
        DocumentSnapshot document = task.getResult();
        if (document.exists()) {
            // 直接取指定字段,SDK自动做类型转换,无需先取整个文档Map
            String userComment = document.getString("Comment");
            String mName = document.getString("Movie Name");
            // 非空判断后再赋值给TextView
            if (userComment != null) {
                commentTextView.setText(userComment);
            }
            if (mName != null) {
                movieNameTextView.setText(mName);
            }
        } else {
            Toast.makeText(MovieDetails.this, "No Such Document", Toast.LENGTH_SHORT).show();
        }
    } else {
        Toast.makeText(MovieDetails.this, "Get Data Failed: " + task.getException().getMessage(), Toast.LENGTH_SHORT).show();
    }
});

情况2:数据存储在Users集合对应用户文档的All Comments嵌套Map中(对应第二种写入逻辑)

先读取外层嵌套Map,再从Map中取内部字段,同步做非空校验:

String userID = firebaseAuth.getCurrentUser().getUid();
// 注意修正原集合名末尾多余的空格
DocumentReference userDocRef = firebaseFirestore.collection("Users").document(userID);
userDocRef.get().addOnCompleteListener(task -> {
    if (task.isSuccessful()) {
        DocumentSnapshot document = task.getResult();
        if (document.exists()) {
            // 先取外层的All Comments嵌套字段
            Map<String, Object> allCommentsMap = (Map<String, Object>) document.get("All Comments");
            if (allCommentsMap != null) {
                // 从嵌套Map中取目标字段
                String userComment = (String) allCommentsMap.get("Comment");
                String mName = (String) allCommentsMap.get("Movie Name");
                if (userComment != null) {
                    commentTextView.setText(userComment);
                }
                if (mName != null) {
                    movieNameTextView.setText(mName);
                }
            }
        } else {
            Toast.makeText(MovieDetails.this, "User Document Not Exist", Toast.LENGTH_SHORT).show();
        }
    } else {
        Toast.makeText(MovieDetails.this, "Get Data Failed: " + task.getException().getMessage(), Toast.LENGTH_SHORT).show();
    }
});

注意事项

  • 第二种写入代码里的集合名Users 末尾多了一个空格,读取时如果不带空格会找不到文档,建议统一修改为无多余空格的Users
  • 尽量不要用getData()获取整个文档Map再拆字段,直接调用getString()、get()等方法取指定字段,SDK会自动处理类型转换,降低类型转换错误概率
  • 所有从Firestore取到的对象都要做非空判断,避免字段不存在、文档不存在等场景触发空指针崩溃

内容的提问来源于stack exchange,提问作者Titan Demon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 08:01:11