如何在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
相关产品推荐
相关产品推荐

