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

Jetpack Compose读取Cloud Firestore报错:For-loop需iterator()方法

解决Jetpack Compose中Firestore读取数据的迭代器错误

在Jetpack Compose中从Cloud Firestore读取数据时,遇到错误提示:"For-loop range must have an 'iterator()' method",错误指向for (document in documents)语句中的documents变量。以下是问题代码分析及解决方案:

初始代码

fun Varer() {
    var firestore: FirebaseFirestore = FirebaseFirestore.getInstance()
    var docRef = firestore.collection("varer").document("varer")
    var source = Source.DEFAULT

    docRef.get(source).addOnSuccessListener { documents ->
        for (document in documents) {
            Log.d(TAG, "${document.id} => ${document.data}")
            var v1 = VareFB(
                tittel = document["tittel"].toString(),
                pris = document.getDouble("pris"),
                beskrivelse = document["beskrivelse"].toString(),
                bildeID = document["bildeID"].toString(),
            )
            varerListe.add(v1)
            Log.d(TAG, document["tittel"].toString())
            Log.d(TAG, v1.toString())
        }
    }
    .addOnFailureListener { exception ->
        Log.w(TAG, "Feil med henting av varer: ", exception)
    }
}
data class VareFB (
    val tittel: String,
    val pris: Double?,
    val beskrivelse: String,
    val bildeID: String,
) {
    @Exclude
    fun toMap(): Map<String, Any?> {
        return mapOf(
            "tittel" to tittel,
            "pris" to pris,
            "beskrivelse" to beskrivelse,
            "bildeID" to bildeID,
        )
    }
}
object VarerObject {
    var varerListe = mutableListOf<VareFB>()
}

修改后的代码

fun Varer() {
    var firestore: FirebaseFirestore = FirebaseFirestore.getInstance()
    var docRef = firestore.collection("varer").document("varer")
    var source = Source.DEFAULT

    docRef.get(source).addOnSuccessListener { snapshot ->
        for (document in snapshot.documents) {
            Log.d(TAG, "${document.id} => ${document.data}")
            var v1 = VareFB(
                tittel = document["tittel"].toString(),
                pris = document.getDouble("pris"),
                beskrivelse = document["beskrivelse"].toString(),
                bildeID = document["bildeID"].toString(),
            )
            varerListe.add(v1)
            Log.d(TAG, document["tittel"].toString())
            Log.d(TAG, v1.toString())
        }
    }
    .addOnFailureListener { exception ->
        Log.w(TAG, "Feil med henting av varer: ", exception)
    }
}

问题分析

  1. 初始代码错误原因:
    调用firestore.collection("varer").document("varer")获取的是单个文档,对应DocumentSnapshot对象。该对象不是可迭代集合,无法用for (document in documents)遍历,因此触发迭代器错误。

  2. 修改后代码的问题:
    DocumentSnapshot没有documents属性,snapshot.documents会导致新的编译错误,本质是混淆了单个文档与集合查询的区别。

解决方案

根据数据结构分两种情况处理:

情况1:varer是集合,包含多个文档

若varer集合下有多个独立商品文档,直接查询整个集合:

fun fetchVarer() {
    val firestore = FirebaseFirestore.getInstance()
    val collectionRef = firestore.collection("varer")
    val source = Source.DEFAULT

    collectionRef.get(source).addOnSuccessListener { querySnapshot ->
        val newVarerList = mutableListOf<VareFB>()
        // querySnapshot.documents是可迭代的文档列表
        for (document in querySnapshot.documents) {
            Log.d(TAG, "${document.id} => ${document.data}")
            val vare = VareFB(
                tittel = document["tittel"].toString(),
                pris = document.getDouble("pris"),
                beskrivelse = document["beskrivelse"].toString(),
                bildeID = document["bildeID"].toString(),
            )
            newVarerList.add(vare)
        }
        // 更新全局列表(Compose中建议用MutableStateListOf实现UI自动刷新)
        VarerObject.varerListe.clear()
        VarerObject.varerListe.addAll(newVarerList)
    }
    .addOnFailureListener { exception ->
        Log.w(TAG, "Feil med henting av varer: ", exception)
    }
}

情况2:varer是单个文档,内部包含商品数组

若单个varer文档中存储了商品数组字段,需取出数组再遍历:

fun fetchVarer() {
    val firestore = FirebaseFirestore.getInstance()
    val docRef = firestore.collection("varer").document("varer")
    val source = Source.DEFAULT

    docRef.get(source).addOnSuccessListener { documentSnapshot ->
        // 取出文档中的数组字段(假设字段名为"varer")
        val varerArray = documentSnapshot.get("varer") as? List<Map<String, Any>>
        varerArray?.forEach { item ->
            val vare = VareFB(
                tittel = item["tittel"].toString(),
                pris = item["pris"] as? Double,
                beskrivelse = item["beskrivelse"].toString(),
                bildeID = item["bildeID"].toString(),
            )
            VarerObject.varerListe.add(vare)
        }
    }
    .addOnFailureListener { exception ->
        Log.w(TAG, "Feil med henting av varer: ", exception)
    }
}

额外提示

在Jetpack Compose中,直接修改全局可变列表varerListe不会触发UI自动刷新。建议将varerListe改为mutableStateListOf(),或使用StateFlow管理数据状态,确保数据更新时UI同步刷新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 15:55:19