按类别过滤可流动的对象列表并将其分组到另一个流动对象列表中

Posted

技术标签:

【中文标题】按类别过滤可流动的对象列表并将其分组到另一个流动对象列表中【英文标题】:filter flowable list of object by category and group into another list of object in flow 【发布时间】:2021-12-23 17:00:43 【问题描述】:

是否可以按类别过滤和分组Flow<List<Object A>>

我发现问题非常相似 here ,但没有运气:(

我在这里分享我尝试过的方法,

viewModel 中的代码:

class HomeViewModel: ViewModel() 

 data class Car(val id: Int, val name: String, val category: Int)
 data class CarsByCategory(val categoryId:Int, val categoryName: String, val carList: List<Car>)

    private val categoryList =
        mapOf<Int, String>(1 to "Audi", 2 to "BMW", 3 to "Chevrolet", 4 to "Dodge", 5 to "Others")

    private val mutableCarList: MutableList<CarsByCategory> = mutableListOf()
    private val _mutableStateFlowCarList: MutableStateFlow<List<CarsByCategory>> = MutableStateFlow(emptyList())
    
    val filteredCarList: StateFlow<List<CarsByCategory>> = _mutableStateFlowCarList
    
    private fun getAllCarsAsFlow(): Flow<List<Car>> 
        val cars = listOf(
            Car(id = 1, name = "A1", category = 1),
            Car(id = 1, name = "A2", category = 1),
            Car(id = 1, name = "BMW X1", category = 2),
            Car(id = 1, name = "BMW X7", category = 2),
            Car(id = 1, name = "M Roadster", category = 2),
            Car(id = 1, name = "Bolt EUV", category = 3),
            Car(id = 1, name = "Blazer", category = 3),
            Car(id = 1, name = "Challenger", category = 4),
            Car(id = 1, name = "Neon", category = 4),
            Car(id = 1, name = "Frontier", category = 5)
        )
        return flowOf(cars)
    
  
   private fun filterCarByCategory()
        getAllCarsAsFlow().map  carList ->
            for (key in categoryList.keys) 
                val filteredList = carList.filter  car -> car.category == key 
                mutableCarList.add(
                    CarsByCategory(
                        categoryId = key,
                         categoryName= categories.getValue(key),
                        carList = filteredList
                    )
                )
            
            _mutableStateFlowCarList.value = mutableCarList.toList()
        
    

    init 
        filterCarByCategory()
    

片段中的代码:

  ....

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) 

        lifecycleScope.launchWhenStarted 
            homeViewModel.filteredCarList.collect 
                Log.d(TAG, "onViewCreated: $it.size")
//                here getting car list size is 0
            
        
    

  ...

我不知道这是不是正确的方法,请告诉我如何使用流解决这个问题

【问题讨论】:

【参考方案1】:

流在被收集之前不会发出任何值。所以你需要收集你的流量:

private fun filterCarByCategory()
    viewModelScope.launch 
        getAllCarsAsFlow().collect  carList ->
            // Rest everything same
        
    

编辑:如果 _mutableStateFlowCarList 的唯一目的是向 UI 提供数据,那么您无需在此处使用 StateFlow,只需普通的 Flow 即可。 p>

val filteredCarList = getAllCarsAsFlow().map  carList ->
    categoryList.map  (id, name) ->
        CarsByCategory (
            categoryId = id,
            categoryName = name,
            carList = carList.filter  car -> car.category == id 
        )
    

【讨论】:

是的,但是我们可以根据我们的要求将现有数据流流转换为包含过滤列表的另一种类型,然后在 UI 屏幕上而不是在 ViewModel 上收集。我的意思是有什么简单的方法可以使用 flow 来做同样的事情吗? 使用StateFlow有什么特殊原因吗?为什么不是普通的Flow?可以使用 map 运算符生成普通的 Flow,然后您可以在 UI 中收集该运算符。 另外,我上面写的代码仍然使用_mutableStateFlowCarList,你可以在 UI 中收集它(就像你现在所做的那样)。唯一的变化是将map 替换为collect 我不这么认为,我们可以在外部流上发出 mutableCarList 值还是需要为它创建另一个流? 另外,在您的原始代码中,您没有在任何地方清除 mutableCarList。是故意的吗?

以上是关于按类别过滤可流动的对象列表并将其分组到另一个流动对象列表中的主要内容,如果未能解决你的问题,请参考以下文章

Flowable入门系列文章90 - 一般可流动的REST原则 01

谷歌更新其社区人员流动报告 帮助了解民众遵守封锁令的情况

既有方向又会动的线,包你学会制作按箭头方向流动的线(three.js实战3)

苹果13微信下拉白色流动液体

面向对象--作业二

我如何更好地在 woocommerce rest api 中按类别对产品进行分组?