Android MVVM架构中如何动态创建ChipGroup等容器的子视图
问题结论
完全可以通过Data Binding实现ChipGroup/RadioGroup的动态子视图添加,必须借助自定义BindingAdapter完成,你原有MVC模式下的视图操作逻辑只要封装到BindingAdapter中,就完全符合MVVM分层规范,不需要改动现有ViewModel、RecyclerView的绑定逻辑。
具体实现方案
- 第一步:编写通用自定义BindingAdapter
把动态添加子视图的逻辑封装到BindingAdapter中,这部分逻辑属于视图渲染逻辑,不会破坏MVVM分层(ViewModel不直接接触View实例):
import android.view.LayoutInflater import androidx.core.view.ViewCompat import androidx.databinding.BindingAdapter import com.google.android.material.chip.Chip import com.google.android.material.chip.ChipGroup import com.your.package.R import com.your.package.databinding.YourItemLayoutBinding // 替换成你自己的列表项Binding类 @BindingAdapter("sizeOptionList") fun ChipGroup.bindSizeOptions(sizeList: List<String>?) { // 先清空原有子视图,避免重复添加 removeAllViews() if (sizeList.isNullOrEmpty()) return val inflater = LayoutInflater.from(context) sizeList.forEach { sizeText -> val chip = (inflater.inflate(R.layout.chip_item, this, false) as Chip).apply { text = sizeText id = ViewCompat.generateViewId() // 可选:绑定选中事件,把选中结果直接回传给对应ItemViewModel setOnCheckedChangeListener { _, isChecked -> if (isChecked) { (findViewTreeDataBinding() as? YourItemLayoutBinding) ?.itemViewModel?.selectedSize?.postValue(sizeText) } } } addView(chip) } }
如果要适配RadioGroup,只需要把方法接收的第一个参数换成
RadioGroup,子项inflate为RadioButton即可,逻辑完全通用。
- 第二步:修改列表项XML,直接绑定数据源
不需要在ChipGroup标签内提前写死子视图,直接通过自定义属性绑定ItemViewModel里的size列表即可:
<TextView android:text="@{itemViewModel.data.name}" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <com.google.android.material.chip.ChipGroup android:id="@+id/chipGroupSizeOption" android:layout_width="match_parent" android:layout_height="wrap_content" app:singleSelection="true" app:sizeOptionList="@{itemViewModel.data.size}"> </com.google.android.material.chip.ChipGroup>
注意事项
- 不要在ViewModel层直接持有View引用、执行inflate/addView这类视图操作,ViewModel只负责持有和加工数据,所有视图渲染逻辑统一放在BindingAdapter或View层实现。
- 如果需要实现选中状态回显(比如编辑场景下回显用户之前选过的尺寸),可以给BindingAdapter增加一个接收选中值的参数,加
@InverseBindingAdapter实现双向绑定即可,不需要修改RecyclerView的Adapter逻辑。 - 给动态生成的子View必须手动调用
ViewCompat.generateViewId()生成唯一ID,否则ChipGroup的单选模式、选中状态保存会失效。
内容的提问来源于stack exchange,提问作者Tangibleidea
相关产品推荐
相关产品推荐

