Android Kotlin Firebase:获取两张图片入Bitmap数组遇越界错误求助
问题分析
你遇到的IndexOutOfBoundsException核心原因是Firebase Storage的文件下载是异步操作:你在代码中直接执行bitmapArray.addAll()、shuffle()以及按钮绑定逻辑时,两张图片还没完成下载,此时bitmapArray是空的,访问bitmapArray[index]自然会触发数组越界异常。另外原代码中bitmapArray.addAll(bitmapArray)的写法逻辑错误,空数组执行该操作后依然为空。
解决方案
1. 核心修正思路
等待两张图片的异步下载任务全部完成后,再执行数组复制、打乱和按钮绑定操作,可借助Firebase的Tasks.whenAll()API监听多个异步任务的完成状态。
2. 修改后的完整代码
val aDatabase = FirebaseStorage.getInstance().getReference("all/$imageID1.jpg") val sDatabase = FirebaseStorage.getInstance().getReference("all/$imageID2.jpg") val bitmapArray = mutableListOf<Bitmap>() // 创建第一个图片的下载任务 val downloadTask1 = try { val localFile = File.createTempFile("tempfile", ".jpg") aDatabase.getFile(localFile).addOnSuccessListener { val bitmap = BitmapFactory.decodeFile(localFile.absolutePath) bitmapArray.add(bitmap) }.addOnFailureListener { Log.w("myapplication", "ERROR RETRIEVING IMAGE 1") Toast.makeText(this, "ERROR RETRIEVING IMAGE 1", Toast.LENGTH_SHORT).show() } } catch (e: Exception) { e.printStackTrace() null } // 创建第二个图片的下载任务 val downloadTask2 = try { val localFile = File.createTempFile("tempfile1", ".jpg") sDatabase.getFile(localFile).addOnSuccessListener { val bitmap = BitmapFactory.decodeFile(localFile.absolutePath) bitmapArray.add(bitmap) }.addOnFailureListener { Log.w("myapplication", "ERROR RETRIEVING IMAGE 2") Toast.makeText(this, "ERROR RETRIEVING IMAGE 2", Toast.LENGTH_SHORT).show() } } catch (e: Exception) { e.printStackTrace() null } // 等待两个下载任务全部完成后再执行后续逻辑 if (downloadTask1 != null && downloadTask2 != null) { Tasks.whenAll(downloadTask1, downloadTask2).addOnCompleteListener { task -> if (task.isSuccessful && bitmapArray.size == 2) { // 生成包含重复元素的数组(每个图片各两张,满足2×2配对需求) val cardList = mutableListOf<Bitmap>().apply { addAll(bitmapArray) addAll(bitmapArray) } cardList.shuffle() // 绑定按钮与点击事件 val button1 = findViewById<ImageButton>(R.id.imageButton1) val button2 = findViewById<ImageButton>(R.id.imageButton2) val button3 = findViewById<ImageButton>(R.id.imageButton3) val button4 = findViewById<ImageButton>(R.id.imageButton4) val buttons = listOf(button1, button2, button3, button4) buttons.forEachIndexed { index, button -> button.setOnClickListener { button.setImageBitmap(cardList[index]) } } } else { Log.w("myapplication", "One or both image downloads failed") Toast.makeText(this, "Failed to load images", Toast.LENGTH_SHORT).show() } } }
关键说明
- 用
Tasks.whenAll()确保只有两张图片都成功下载后,才处理数组和按钮逻辑,从根源避免空数组访问。 - 单独创建
cardList存放重复元素,保证最终数组有4个元素,符合2×2卡片配对的需求。 - 增加
bitmapArray.size == 2的判断,避免单张图片下载失败导致的元素不足问题。
内容的提问来源于stack exchange,提问作者Berk Sunduri
相关产品推荐
相关产品推荐

