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

如何在ViewModel中结合RecyclerView存储单选组按钮的选中值

纸杯蛋糕口味选择流程实现方案

1. 核心组件设计

  • 共享ViewModel:作为数据中枢,存储纸杯蛋糕数量和用户选中的口味列表
  • 数量输入Fragment:处理用户输入的纸杯蛋糕数量,同步至ViewModel
  • 口味选择Fragment:通过RecyclerView动态生成对应数量的RadioGroup,绑定选择事件到ViewModel

2. 分步实现代码

步骤1:定义全局ViewModel

创建继承自ViewModel的类,用MutableLiveData存储可观测的数据:

class CupcakeViewModel : ViewModel() {
    // 存储纸杯蛋糕数量
    val cupcakeCount = MutableLiveData<Int>(0)
    // 存储对应位置的选中口味
    val selectedFlavors = MutableLiveData<MutableList<String>>(mutableListOf())
}

步骤2:实现数量输入Fragment

获取用户输入并更新ViewModel,完成后导航到口味选择页面:

// 输入确认按钮点击事件
btn_confirm.setOnClickListener {
    val inputCount = et_cupcake_count.text.toString().toIntOrNull() ?: 0
    if (inputCount > 0) {
        viewModel.cupcakeCount.value = inputCount
        // 导航至口味选择Fragment(需提前配置NavGraph)
        findNavController().navigate(R.id.action_input_to_flavor_fragment)
    }
}

步骤3:动态生成RadioGroup的RecyclerView实现

3.1 列表项布局(item_cupcake_flavor.xml)

每个项包含序号标题和口味选择RadioGroup:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="16dp">

    <TextView
        android:id="@+id/tv_cupcake_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:text="纸杯蛋糕1"/>

    <RadioGroup
        android:id="@+id/rg_flavor_options"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <RadioButton
            android:id="@+id/rb_chocolate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="巧克力"/>

        <RadioButton
            android:id="@+id/rb_vanilla"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="香草"/>

        <RadioButton
            android:id="@+id/rb_strawberry"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="草莓"/>
    </RadioGroup>
</LinearLayout>

3.2 RecyclerView适配器实现

绑定数据并监听RadioGroup选择事件,实时更新ViewModel:

class FlavorAdapter(private val viewModel: CupcakeViewModel) : RecyclerView.Adapter<FlavorAdapter.ViewHolder>() {

    private val count get() = viewModel.cupcakeCount.value ?: 0
    private val flavorList get() = viewModel.selectedFlavors.value ?: mutableListOf()

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val tvNumber: TextView = itemView.tv_cupcake_number
        val rgFlavors: RadioGroup = itemView.rg_flavor_options
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.item_cupcake_flavor, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        // 设置纸杯蛋糕序号
        holder.tvNumber.text = "纸杯蛋糕${position + 1}"

        // 恢复之前的选中状态
        if (position < flavorList.size) {
            when(flavorList[position]) {
                "巧克力" -> holder.rgFlavors.check(R.id.rb_chocolate)
                "香草" -> holder.rgFlavors.check(R.id.rb_vanilla)
                "草莓" -> holder.rgFlavors.check(R.id.rb_strawberry)
            }
        } else {
            holder.rgFlavors.clearCheck()
        }

        // 监听口味选择变化,同步到ViewModel
        holder.rgFlavors.setOnCheckedChangeListener { _, checkedId ->
            val selectedFlavor = when(checkedId) {
                R.id.rb_chocolate -> "巧克力"
                R.id.rb_vanilla -> "香草"
                R.id.rb_strawberry -> "草莓"
                else -> ""
            }
            if (position < flavorList.size) {
                flavorList[position] = selectedFlavor
            } else {
                flavorList.add(selectedFlavor)
            }
            viewModel.selectedFlavors.value = flavorList
        }
    }

    override fun getItemCount(): Int = count
}

3.3 口味选择Fragment初始化RecyclerView

绑定ViewModel并监听数据变化:

class FlavorFragment : Fragment() {
    private lateinit var viewModel: CupcakeViewModel

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.fragment_flavor, container, false)
        // 使用Activity级别的ViewModelProvider,保证与输入Fragment共享实例
        viewModel = ViewModelProvider(requireActivity())[CupcakeViewModel::class.java]

        val recyclerView = view.findViewById<RecyclerView>(R.id.rv_flavor_choices)
        recyclerView.layoutManager = LinearLayoutManager(requireContext())
        val adapter = FlavorAdapter(viewModel)
        recyclerView.adapter = adapter

        // 监听数量变化,自动刷新列表
        viewModel.cupcakeCount.observe(viewLifecycleOwner) {
            adapter.notifyDataSetChanged()
        }

        return view
    }
}

3. 关键注意点

  • 必须使用Activity级别的ViewModelProvider,确保两个Fragment共享同一ViewModel实例
  • 当用户返回输入Fragment修改数量时,RecyclerView会自动刷新对应数量的选择项
  • selectedFlavors会实时同步用户选择,后续可直接从ViewModel中提取数据用于结算或展示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 23:22:35