根据另一个 Spinner 选择 (LiveData) 过滤 Spinner 的 Observed ViewModel 数据
Posted
技术标签:
【中文标题】根据另一个 Spinner 选择 (LiveData) 过滤 Spinner 的 Observed ViewModel 数据【英文标题】:Filter Observed ViewModel data for Spinner based on another Spinners selection (LiveData) 【发布时间】:2021-11-21 17:35:32 【问题描述】:我有两个 Spinner,每个都由 ArrayList 填充,在 Fragment 的 ViewModel 中观察到如下:
InventoryAddEdit 片段
// Observe ProductGroups and populate Spinner
businessViewModel.allAppDataProductGroups.observe(viewLifecycleOwner, productGroupArrayList -> // ArrayList<ProductGroupObject>
if (!productGroupArrayList.isNullOrEmpty())
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, productGroupArrayList)
binding.inventoryAddEditProductGroupSpinner.adapter = adapter
)
// Observe ProductTypes and populate Spinner
businessViewModel.allAppDataProductTypes.observe(viewLifecycleOwner, productTypeArrayList -> // ArrayList<ProductTypeObject>
if (!productTypeArrayList.isNullOrEmpty())
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, productTypeArrayList)
binding.inventoryAddEditProductTypeSpinner.adapter = adapter
binding.inventoryAddEditProductTypeSpinner.setSelection(17) // Sets default value
)
我试图避免将数据保留在 Fragment (MVVM) 中,所以我想知道如何根据第一个 ArrayList 的选择最好地过滤第二个 ArrayList。
我想我可以在第一个微调器上使用onItemSelected
方法来取消观察者并重新附加,然后通过选择第一个微调器来过滤新观察到的 ArrayList。但是,这似乎有点笨拙。另一个想法是在 ViewModel 中创建另一个过滤列表,但这意味着 ViewModel 中有更多数据。
请问还有其他选择吗?
有关信息,ProductGroupObject 和 ProductTypeObject 如下所示:
ProductGroupObject
@IgnoreExtraProperties
data class ProductGroupObject (
//ProductGroup fields (1 fields)
var productGroup: String = "",
@ServerTimestamp
var dateEditedTimestamp: Date? = null,
@Exclude @set:Exclude @get:Exclude
var productGroupID: String = ""
) : Serializable
override fun toString(): String
return productGroup
ProductTypeObject
@IgnoreExtraProperties
data class ProductTypeObject (
//ProductType fields (2 fields)
var productType: String = "",
var productGroup: String = "",
@ServerTimestamp
var dateEditedTimestamp: Date? = null,
@Exclude @set:Exclude @get:Exclude
var productTypeID: String = ""
) : Serializable
override fun toString(): String
return productType
fun detailsText(): String
val detailsString = StringBuilder()
if(productTypeID.isNotEmpty()) detailsString.append("$productTypeID\n")
if(productType.isNotEmpty()) detailsString.append("$productType\n")
if(productGroup.isNotEmpty()) detailsString.append("$productGroup\n")
return detailsString.toString()
【问题讨论】:
【参考方案1】:所以我想出的最佳解决方案是为 ViewModel 中的每个 Spinner 数据集创建一个“完整列表”和“过滤列表”+每个 Spinner 的“当前选择”对象(也保存在 ViewModel 中)。
“完整列表”由云数据库在启动时填充,“过滤列表”通过以下代码根据 Spinner 选择进行过滤:
binding.inventoryAddEditProductGroupSpinner.onItemSelectedListener = object: AdapterView.OnItemSelectedListener
override fun onItemSelected(parent:AdapterView<*>?, view: View?, position: Int, id: Long)
val productGroupObject = parent?.selectedItem as ProductGroupObject
if (productGroupObject.productGroupID.isNotEmpty())
businessViewModel.updateCurrentProductGroupVMLiveData(productGroupObject.productGroupID)
这会更新“过滤列表”(过滤“完整列表”),该列表将数据保存到任何链接的 Spinner,如下所示:
fun updateCurrentProductGroupVMLiveData (currentProductGroupId: String)
val newProductGroup = allAppDataProductGroups.value?.find productGroup -> productGroup.productGroupID == currentProductGroupId
_currentProductGroup.value = newProductGroup
if(newProductGroup?.productGroup != null)
val filteredProductsList = allAppDataProductTypes.value?.filter productTypeObject -> productTypeObject.productGroup == newProductGroup.productGroup as ArrayList<ProductTypeObject>
_filteredAppDataProductTypes.value = filteredProductsList
// UPDATE OTHER SPINNERS HERE
Log.d(TAG, "updateCurrentProductGroupVMLiveData(): '_currentProductGroupId.value' updated ($currentProductGroupId)")
我遇到的一个问题是由于 LiveData 的工作方式,视图可以为空,这在以下帖子中得到了解决:Spinner Listener LiveData Issue
【讨论】:
以上是关于根据另一个 Spinner 选择 (LiveData) 过滤 Spinner 的 Observed ViewModel 数据的主要内容,如果未能解决你的问题,请参考以下文章