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

Firestore获取文档名存入List复用 代码返回空值问题排查

问题根因

代码返回空列表的核心原因是误用了Firestore的异步API:

  • Firestore的get()是异步网络请求,调用后不会阻塞当前线程等待结果返回,代码会直接执行到return docunames语句
  • 此时请求还未完成,onSuccess回调还没触发,往docunames里添加文档ID的逻辑根本没有执行,自然返回空列表
  • 等请求真正完成、onSuccess里的代码执行时,方法早已把空列表返回,后续往列表添加数据也无法被方法返回值的调用方及时获取。

另外原代码存在两个额外问题:

  • 方法名拼写错误:getDomumentName应为getDocumentName
  • onFailure是空实现,请求出错时没有任何日志或提示,会大幅提升问题排查难度
正确实现方案

异步API无法直接通过return返回加载结果,需要通过回调机制在数据就绪时传递结果,实现步骤如下:

1. 定义加载结果回调接口

新建回调接口用来接收加载成功/失败的结果:

public interface DocNamesLoadCallback {
    void onLoadSuccess(List<String> docNames);
    void onLoadFailed(Exception e);
}

2. 改造工具类方法

修改DocumentName类的加载方法,不再直接返回列表,接收回调参数在数据加载完成后回传结果:

public class DocumentName {
    private final FirebaseFirestore firestore = FirebaseFirestore.getInstance();

    public void getDocumentName(DocNamesLoadCallback callback) {
        firestore.collection("Quizquestions").get()
                .addOnSuccessListener(queryDocumentSnapshots -> {
                    List<String> docNames = new ArrayList<>();
                    for (DocumentSnapshot snapshot : queryDocumentSnapshots.getDocuments()) {
                        docNames.add(snapshot.getId());
                    }
                    // 数据加载完成,通过回调传递结果
                    callback.onLoadSuccess(docNames);
                })
                .addOnFailureListener(e -> {
                    Log.e("FirestoreErr", "文档名加载失败", e);
                    callback.onLoadFailed(e);
                });
    }
}

3. 调用方法&按需使用

在Activity、Fragment或其他业务逻辑处调用加载方法,拿到结果后可以存在成员变量/单例/ViewModel中,后续需要时直接调用即可:

// 页面的成员变量,用来存储加载完成的文档名列表
private List<String> mDocNames = new ArrayList<>();

// 合适的时机调用加载方法,比如页面onCreate时
private void loadDocNames() {
    DocumentName loader = new DocumentName();
    loader.getDocumentName(new DocNamesLoadCallback() {
        @Override
        public void onLoadSuccess(List<String> docNames) {
            // 拿到结果后赋值给成员变量存储
            mDocNames = docNames;
            // 所有依赖文档列表的逻辑可以在这里触发,比如更新UI、初始化题目逻辑
            Toast.makeText(YourActivity.this, "加载完成,共" + docNames.size() + "个文档", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onLoadFailed(Exception e) {
            Toast.makeText(YourActivity.this, "加载失败:" + e.getMessage(), Toast.LENGTH_SHORT).show();
        }
    });
}

// 后续其他业务逻辑需要用到文档名时,直接操作mDocNames即可,注意要等加载完成后再调用
private void someBusinessMethod() {
    if (mDocNames.isEmpty()) {
        // 列表还没加载完,可以加等待逻辑或者提示加载中
        return;
    }
    // 这里写正常使用列表的逻辑,比如取第一个文档名
    String firstDoc = mDocNames.get(0);
}
注意事项
  • 所有依赖文档列表的逻辑,要么放在onLoadSuccess回调中执行,要么增加加载状态判断,避免在列表未加载完成时读取到空值
  • 如果需要全局使用该列表,可以把列表存储在全局单例或者ViewModel中,在应用启动时提前触发加载,后续业务代码直接读取即可

内容的提问来源于stack exchange,提问作者Hemanth kumar B R

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 22:45:44