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

基于Firebase Firestore嵌套字段实现双RecyclerView分类切换问询

解决方案:Firestore数据结构设计与RecyclerView交互实现

一、Firestore数据结构设计

针对你的需求,提供两种可行的嵌套数据方案,按需选择:

1. 子集合嵌套方案(推荐,适配大数据量场景)

将每个公司作为独立文档,在其下创建foods子集合存储对应食品,食品文档包含完整属性。结构示例:

companies (集合)
  |--- 自动生成ID (公司文档)
        |--- name: "XX餐饮有限公司"
        |--- address: "XX路XX号"
        |--- foods (子集合)
              |--- 自动生成ID (食品文档)
                    |--- name: "招牌红烧肉"
                    |--- price: 48.0
                    |--- ingredients: ["五花肉", "八角", "生抽"]
                    |--- shelfLife: "7天"

Kotlin创建代码:

// 创建公司文档
val companyRef = FirebaseFirestore.getInstance().collection("companies").document()
companyRef.set(mapOf(
    "name" to "XX餐饮有限公司",
    "address" to "XX路XX号"
)).addOnSuccessListener {
    // 为该公司添加食品
    val foodRef = companyRef.collection("foods").document()
    foodRef.set(mapOf(
        "name" to "招牌红烧肉",
        "price" to 48.0,
        "ingredients" to listOf("五花肉", "八角", "生抽"),
        "shelfLife" to "7天"
    ))
}

2. 数组嵌套字段方案(适合小数据量、无需单独更新食品的场景)

直接在公司文档中用数组字段存储食品列表,所有食品属性嵌套在数组元素中。结构示例:

companies (集合)
  |--- 自动生成ID (公司文档)
        |--- name: "XX便利店"
        |--- foods: [
              {
                "name": "矿泉水",
                "price": 2.0,
                "stock": 100
              },
              {
                "name": "全麦面包",
                "price": 5.0,
                "stock": 50
              }
            ]

Kotlin创建代码:

val companyData = mapOf(
    "name" to "XX便利店",
    "foods" to listOf(
        mapOf(
            "name" to "矿泉水",
            "price" to 2.0,
            "stock" to 100
        ),
        mapOf(
            "name" to "全麦面包",
            "price" to 5.0,
            "stock" to 50
        )
    )
)
FirebaseFirestore.getInstance().collection("companies").add(companyData)

二、按公司名称分类加载食品

1. 点击公司后加载对应食品(子集合方案)

假设你已获取点击的公司文档ID,直接查询该公司下的foods子集合:

// companyId为点击的公司文档ID
FirebaseFirestore.getInstance()
    .collection("companies")
    .document(companyId)
    .collection("foods")
    .get()
    .addOnSuccessListener { snapshot ->
        val foodList = snapshot.documents.map { doc ->
            doc.toObject(Food::class.java)!! // 需提前定义Food数据类
        }
        // 更新第一个RecyclerView的适配器数据
        foodAdapter.submitList(foodList)
    }

2. 点击公司后加载对应食品(数组嵌套方案)

从公司文档中直接读取foods数组字段:

FirebaseFirestore.getInstance()
    .collection("companies")
    .document(companyId)
    .get()
    .addOnSuccessListener { doc ->
        if (doc.exists()) {
            val foods = doc.get("foods") as List<Map<String, Any>>
            val foodList = foods.map {
                Food(
                    name = it["name"] as String,
                    price = it["price"] as Double,
                    stock = it["stock"] as Int
                )
            }
            foodAdapter.submitList(foodList)
        }
    }

3. 按公司名称筛选(可选)

如果需要通过公司名称搜索食品,先查询匹配的公司,再加载其食品:

FirebaseFirestore.getInstance()
    .collection("companies")
    .whereEqualTo("name", "XX餐饮有限公司")
    .get()
    .addOnSuccessListener { companySnapshot ->
        if (companySnapshot.isEmpty) return@addOnSuccessListener
        val companyDoc = companySnapshot.documents[0]
        // 后续加载该公司的食品(参考上述子集合/数组方案)
    }

三、RecyclerView交互实现

食品条目点击后加载属性到第二个RecyclerView

定义一个Property数据类存储属性名和值,点击食品时将其属性转换为List<Property>,更新第二个RecyclerView:

// 提前定义Property数据类:data class Property(val key: String, val value: String)
foodItemView.setOnClickListener {
    val selectedFood = foodList[adapterPosition]
    val propertyList = mutableListOf<Property>().apply {
        add(Property("食品名称", selectedFood.name))
        add(Property("售价", "${selectedFood.price}元"))
        add(Property("食材", selectedFood.ingredients.joinToString()))
        add(Property("保质期", selectedFood.shelfLife))
        // 按需添加其他属性
    }
    // 更新第二个RecyclerView适配器
    propertyAdapter.submitList(propertyList)
    // 若第二个RecyclerView初始隐藏,此处设置为可见
    propertyRecyclerView.visibility = View.VISIBLE
}

四、关键注意事项

  • 优先选择子集合方案:食品数据频繁更新、数量较多时,子集合支持单独修改某款食品,查询性能更优。
  • 避免用公司名称作为文档ID:名称可能重复,建议用Firestore自动生成的ID或公司唯一标识(如统一社会信用代码)。
  • 数据类适配Firestore:确保Company、Food等数据类有无参构造函数,或使用Kotlin序列化注解@Serializable。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:55:30