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

Android Kotlin:如何通过LiveData<String>过滤Room返回的LiveData<Map>?

Kotlin中过滤Room返回的LiveData<Map<Server, List>>数据

你可以通过组合两个LiveData(数据源和搜索关键词),在数据变化时执行过滤逻辑来实现需求。核心思路是:监听数据源和搜索词的更新,对每个Server下的Group列表进行筛选,只保留描述包含搜索关键词的Group,同时移除过滤后无Group的Server条目。

数据类定义

data class Server(
    val serverId: Int
)

data class Group(
    val serverId: Int,
    val groupId: Int,
    val description: String
)

实现方案

使用MediatorLiveData监听两个LiveData的变化,任一数据更新时自动执行过滤操作:

import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.LiveData

// 从Room获取的数据源
val serverGroupsLiveData: LiveData<Map<Server, List<Group>>> = ...
// 搜索关键词LiveData
val searchQueryLiveData: LiveData<String> = ...

// 过滤后的结果LiveData
val filteredServerGroupsLiveData: LiveData<Map<Server, List<Group>>> = MediatorLiveData<Map<Server, List<Group>>>().apply {
    // 封装过滤逻辑
    fun filterData(serverGroups: Map<Server, List<Group>>?, query: String?): Map<Server, List<Group>> {
        val lowerCaseQuery = query?.trim()?.lowercase() ?: ""
        return serverGroups?.mapValues { (_, groups) ->
            groups.filter { group ->
                group.description.lowercase().contains(lowerCaseQuery)
            }
        }?.filterValues { it.isNotEmpty() } ?: emptyMap()
    }

    // 监听数据源变化
    addSource(serverGroupsLiveData) {
        value = filterData(it, searchQueryLiveData.value)
    }
    // 监听搜索词变化
    addSource(searchQueryLiveData) {
        value = filterData(serverGroupsLiveData.value, it)
    }
}

逻辑说明

  1. 大小写兼容:将搜索词和Group描述统一转为小写,实现不区分大小写的搜索(如需区分大小写,移除lowercase()即可)。
  2. Group筛选:对每个Server对应的Group列表,保留描述包含搜索关键词的条目。
  3. 清理空条目:过滤后移除无Group的Server,避免显示空Server项。
  4. 实时更新:数据源或搜索词发生变化时,自动重新计算并发布最新结果。

简化写法(依赖lifecycle-livedata-ktx)

如果项目引入androidx.lifecycle:lifecycle-livedata-ktx,可以用combine函数简化实现:

import androidx.lifecycle.liveData
import androidx.lifecycle.combine

val filteredServerGroupsLiveData = liveData {
    combine(serverGroupsLiveData, searchQueryLiveData) { serverGroups, query ->
        val lowerCaseQuery = query.trim().lowercase()
        serverGroups.mapValues { (_, groups) ->
            groups.filter { it.description.lowercase().contains(lowerCaseQuery) }
        }.filterValues { it.isNotEmpty() }
    }.collect { emit(it) }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 13:30:54