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

Firebase Storage链接未写入实时数据库问题排查

问题根源:异步操作的执行顺序搞反了

哥们,你这问题典型的异步操作时序错误——Firebase Storage的文件上传、下载链接获取都是后台异步执行的,但你的代码在这些异步任务还没完成(还没把真实链接赋值给uploadData)的时候,就已经把uploadData写入实时数据库了。

咱们捋下你代码的实际执行流程:

  1. 点击按钮,启动图片和文档的异步上传任务(这俩任务在后台跑,不会阻塞主线程)
  2. 立刻关闭进度框,给uploadData设置name和info
  3. 直接把uploadData写入数据库(这时候imgURL和docURL还是默认的空值/Null,因为异步任务还没跑完)
  4. 过了一会儿,异步任务完成,才把真实链接赋值给uploadData,但这时候数据库已经写完了,自然看不到链接

解决方案:等所有异步任务完成后再写数据库

核心思路是:必须确保图片和文档的下载链接都已经拿到(或者确认上传失败),再执行数据库写入操作。这里给你两种实现方式,选顺手的用就行。

方式一:用计数跟踪任务完成状态(易理解)

updata.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        progressDialog.setTitle("Uploading Files");
        progressDialog.show();

        final UploadData uploadData = new UploadData();
        String info = infoText.getText().toString();
        String event = eventName.getText().toString();
        uploadData.setName(event);
        uploadData.setInfo(info);

        // 统计需要执行的上传任务数
        int totalTasks = 0;
        if (ImgPathUri != null) totalTasks++;
        if (DocPathUri != null) totalTasks++;
        // 用来记录已完成的任务数
        int completedTasks = 0;

        // 如果没有文件要上传,直接写数据库
        if (totalTasks == 0) {
            writeToDatabase(event, uploadData);
            progressDialog.dismiss();
            return;
        }

        // 上传图片逻辑
        if (ImgPathUri != null) {
            StorageReference imgRef = storageReference.child(StoragePath + System.currentTimeMillis() + "." + getExtension(ImgPathUri));
            imgRef.putFile(ImgPathUri)
                    .addOnSuccessListener(taskSnapshot -> {
                        taskSnapshot.getStorage().getDownloadUrl()
                                .addOnSuccessListener(uri -> {
                                    uploadData.setImgURL(uri.toString());
                                    completedTasks++;
                                    checkAndWrite(completedTasks, totalTasks, event, uploadData);
                                })
                                .addOnFailureListener(e -> {
                                    Toast.makeText(addEventActivity.this, "图片链接获取失败", Toast.LENGTH_SHORT).show();
                                    completedTasks++;
                                    checkAndWrite(completedTasks, totalTasks, event, uploadData);
                                });
                    })
                    .addOnFailureListener(e -> {
                        Toast.makeText(addEventActivity.this, "图片上传失败", Toast.LENGTH_SHORT).show();
                        completedTasks++;
                        checkAndWrite(completedTasks, totalTasks, event, uploadData);
                    });
        }

        // 上传文档逻辑
        if (DocPathUri != null) {
            StorageReference docRef = storageReference.child(StoragePath + System.currentTimeMillis() + "." + getExtension(DocPathUri));
            docRef.putFile(DocPathUri)
                    .addOnSuccessListener(taskSnapshot -> {
                        taskSnapshot.getStorage().getDownloadUrl()
                                .addOnSuccessListener(uri -> {
                                    uploadData.setDocURL(uri.toString());
                                    completedTasks++;
                                    checkAndWrite(completedTasks, totalTasks, event, uploadData);
                                })
                                .addOnFailureListener(e -> {
                                    Log.e("TAG", "文档链接获取失败", e);
                                    completedTasks++;
                                    checkAndWrite(completedTasks, totalTasks, event, uploadData);
                                });
                    })
                    .addOnFailureListener(e -> {
                        Toast.makeText(addEventActivity.this, "文档上传失败", Toast.LENGTH_SHORT).show();
                        completedTasks++;
                        checkAndWrite(completedTasks, totalTasks, event, uploadData);
                    });
        }
    }

    // 检查所有任务是否完成,完成则写入数据库
    private void checkAndWrite(int completed, int total, String event, UploadData data) {
        if (completed == total) {
            progressDialog.dismiss();
            writeToDatabase(event, data);
            Toast.makeText(addEventActivity.this, "数据已保存", Toast.LENGTH_SHORT).show();
        }
    }

    // 封装数据库写入逻辑
    private void writeToDatabase(String event, UploadData data) {
        databaseReference.child(event).setValue(data);
    }
});

方式二:用Firebase Tasks组合异步任务(更简洁)

如果你的Firebase SDK版本≥16.0.0,可以用Tasks.whenAllSuccess()来组合多个异步任务,代码更清爽:

updata.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        progressDialog.setTitle("Uploading Files");
        progressDialog.show();

        final UploadData uploadData = new UploadData();
        String info = infoText.getText().toString();
        String event = eventName.getText().toString();
        uploadData.setName(event);
        uploadData.setInfo(info);

        // 把上传逻辑封装成返回Task<String>的方法
        Task<String> imgTask = ImgPathUri != null ? uploadFile(ImgPathUri) : Tasks.forResult(null);
        Task<String> docTask = DocPathUri != null ? uploadFile(DocPathUri) : Tasks.forResult(null);

        // 等待两个任务都完成
        Tasks.whenAllSuccess(imgTask, docTask)
                .addOnSuccessListener(results -> {
                    progressDialog.dismiss();
                    String imgLink = (String) results.get(0);
                    String docLink = (String) results.get(1);
                    if (imgLink != null) uploadData.setImgURL(imgLink);
                    if (docLink != null) uploadData.setDocURL(docLink);
                    databaseReference.child(event).setValue(uploadData);
                    Toast.makeText(addEventActivity.this, "数据已保存", Toast.LENGTH_SHORT).show();
                })
                .addOnFailureListener(e -> {
                    progressDialog.dismiss();
                    Toast.makeText(addEventActivity.this, "上传失败", Toast.LENGTH_SHORT).show();
                });
    }

    // 通用上传方法,返回获取下载链接的Task
    private Task<String> uploadFile(Uri fileUri) {
        StorageReference fileRef = storageReference.child(StoragePath + System.currentTimeMillis() + "." + getExtension(fileUri));
        return fileRef.putFile(fileUri)
                .continueWithTask(task -> fileRef.getDownloadUrl())
                .continueWithTask(task -> Tasks.forResult(task.getResult().toString()));
    }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 07:42:44