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

基于Spinner选中项过滤关联Spinner的ViewModel LiveData数据(MVVM)

符合MVVM规范的双Spinner联动实现方案

核心思路

用Jetpack Lifecycle组件提供的Transformations.switchMap实现响应式过滤,仅需在ViewModel中新增一个选中项的LiveData作为过滤触发源,过滤逻辑全在ViewModel侧完成,Fragment完全不持有业务数据,也无需手动维护过滤后的列表。

ViewModel 代码修改

// 原有全量数据LiveData无需修改
val allAppDataProductGroups: LiveData<ArrayList<ProductGroupObject>> = ...
val allAppDataProductTypes: LiveData<ArrayList<ProductTypeObject>> = ...

// 新增:存储当前选中的产品组
val selectedProductGroup = MutableLiveData<String?>()

// 新增:自动响应过滤的产品类型列表
val filteredProductTypes = Transformations.switchMap(selectedProductGroup) { group ->
    Transformations.map(allAppDataProductTypes) { allTypes ->
        when {
            group.isNullOrEmpty() -> allTypes
            else -> ArrayList(allTypes.filter { it.productGroup == group })
        }
    }
}

// 供Fragment调用更新选中的产品组
fun updateSelectedGroup(groupName: String) {
    // 重复选中不触发过滤,减少无用计算
    if (selectedProductGroup.value != groupName) {
        selectedProductGroup.value = groupName
    }
}

Fragment 代码修改

// 产品组Spinner观察者,新增选中监听
businessViewModel.allAppDataProductGroups.observe(viewLifecycleOwner, { productGroupArrayList -> 
    if (!productGroupArrayList.isNullOrEmpty()){
        val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, productGroupArrayList)
        binding.inventoryAddEditProductGroupSpinner.adapter = adapter
        // 绑定选中事件
        binding.inventoryAddEditProductGroupSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
                val selectedGroup = parent?.getItemAtPosition(position) as ProductGroupObject
                businessViewModel.updateSelectedGroup(selectedGroup.productGroup)
            }
            override fun onNothingSelected(parent: AdapterView<*>?) {
                businessViewModel.updateSelectedGroup("")
            }
        }
    }
})

// 替换原有的全量产品类型观察者,改为观察过滤后的列表
businessViewModel.filteredProductTypes.observe(viewLifecycleOwner, { filteredTypeList -> 
    if (!filteredTypeList.isNullOrEmpty()){
        val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, filteredTypeList)
        binding.inventoryAddEditProductTypeSpinner.adapter = adapter
        // 自适应默认选中位置,避免索引越界
        val defaultPos = if (filteredTypeList.size > 17) 17 else 0
        binding.inventoryAddEditProductTypeSpinner.setSelection(defaultPos)
    }
})

方案优势

  1. 完全符合MVVM规范:Fragment仅做视图交互,无业务数据持有,过滤逻辑全在ViewModel中实现,可单独单元测试
  2. 无冗余代码:不需要频繁注销/注册观察者,全量数据更新、选中项变更时都会自动触发重新过滤
  3. 内存占用极低:过滤后的列表为临时计算生成,无需手动维护持久化存储,旧列表会被自动GC回收,不会增加冗余内存占用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 12:57:03