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

为何Firebase Storage异步操作中uriList.add未生效且日志顺序异常?

问题根源
  • 异步操作导致顺序异常:Firebase Storage的listAll()和downloadUrl获取都是异步非阻塞任务,主线程调用这些方法后会立刻执行后续的打印代码,不会等待异步任务完成。所以日志顺序会是firstTmpUri→thirdTmpUri→secondTmpUri,异步回调里的代码要等后台任务跑完才会执行。
  • 不是add没生效,是打印时机不对:uriList.add(task.result)实际是执行了,但你在异步任务还没完成时就打印了uriList,此时添加操作还没执行,所以看到空列表。tmpUrl回到初始值也是同理,异步回调里的赋值操作还没触发,thirdTmpUri就已经输出了初始值。
修复方案(推荐用Kotlin协程)

先确保项目引入Firebase Storage的KTX扩展库(版本20.0.0及以上),把异步操作转为挂起函数,确保所有Uri获取完成后再处理:

private suspend fun getPhotoList() {
    val fileName = intent.getStringExtra("fileName") ?: return

    Log.d("fileNameChecking", "$fileName")

    val listRef = FirebaseStorage.getInstance().reference.child("image").child(fileName)
    var tmpUrl: Uri = Uri.parse(fileName)
    Log.d("firstTmpUri", "$tmpUrl")

    try {
        // 等待listAll任务完成
        val listResult = listRef.listAll().await()
        for (item in listResult.items) {
            // 等待单个文件的downloadUrl获取完成
            val downloadUri = item.downloadUrl.await()
            tmpUrl = downloadUri
            Log.d("tmpUri", "$tmpUrl")
            Log.d("urichecking2", "$downloadUri")
            uriList.add(downloadUri)
        }
        // 所有Uri都获取完成后再打印
        Log.d("thirdTmpUri", "$tmpUrl")
        Log.d("urichecking", "$uriList")
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

调用时要放在协程作用域内(比如Activity中):

lifecycleScope.launch {
    getPhotoList()
}
不用协程的替代方案

如果不想用协程,可以用CountDownLatch等待所有下载任务完成:

private fun getPhotoList() {
    val fileName = intent.getStringExtra("fileName") ?: return

    Log.d("fileNameChecking", "$fileName")

    val listRef = FirebaseStorage.getInstance().reference.child("image").child(fileName)
    var tmpUrl: Uri = Uri.parse(fileName)
    Log.d("firstTmpUri", "$tmpUrl")

    listRef.listAll()
        .addOnSuccessListener { listResult ->
            // 根据文件数量初始化计数器
            val latch = CountDownLatch(listResult.items.size)
            for (item in listResult.items) {
                item.downloadUrl.addOnCompleteListener { task ->
                    if (task.isSuccessful) {
                        tmpUrl = task.result
                        Log.d("secondTmpUri", "$tmpUrl")
                        Log.d("urichecking2", "${task.result}")
                        uriList.add(task.result)
                    }
                    // 完成一个任务就将计数器减1
                    latch.countDown()
                }.addOnFailureListener {
                    it.printStackTrace()
                    latch.countDown()
                }
            }
            // 开启线程等待所有任务完成
            Thread {
                try {
                    latch.await()
                    // 回到主线程执行打印或UI更新操作
                    runOnUiThread {
                        Log.d("thirdTmpUri", "$tmpUrl")
                        Log.d("urichecking", "$uriList")
                    }
                } catch (e: InterruptedException) {
                    e.printStackTrace()
                }
            }.start()
        }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 02:20:26