Home > OS >  Filter LiveData<Map> by another LiveData<String> android kotlin
Filter LiveData<Map> by another LiveData<String> android kotlin

Time:10-27

I have a LiveData<Map<A, List<B >> that comes from Room Database and I have also a searchQuery that I want to Filter the B objects by. For example,

data class Server(
   val serverId: Int
)

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

LiveData<Map<Server, List<Group>>

So I have 
Server(100)
Group(100, 1, "AAAA")
Group(100, 2, "AAAB")
Group(100, 3, "AABB")

Server(200)
Group(200, 1, "AAAA")
Group(200, 2, "AAAB")
Group(200, 3, "AABB")

Now, I have a searchableString = "BB" So the LiveData I want it to be filtered on the description field and the result must be

Server(100)
Group(100, 3, "AABB")

Server(200)
Group(200, 3, "AABB")

Is there any way to do this on Kotlin?

CodePudding user response:

First write an extension function to filter your map:

fun Map<Server, List<Group>>.filterGroups(descFilter: String) = mapValues { _, groups ->
    groups.filter { descFilter in it.description }
}

If you want to eliminate empty servers, you could tack on a .filter { _, groups -> groups.isNotEmpty() } to the end of the above function.

Assuming your LiveData is in a view model, I would create a private MutableLiveData for the search term with a public property to change it. Then use switchMap to produce the final result based on your input.

val sourceMapFromRoom: LiveData<Map<Server, List<Group>> = //...

private val _searchFilter = MutableLiveData<String>("")

val searchFilter: String
    get() = _searchFilter.value
    set(value) { _searchFilter.value = value }

val filteredMap = _searchFilter.switchMap { searchString ->
    sourceMapFromRoom.map { it.filterGroups(searchString) }
}

switchMap is the LiveData equivalent of flatMapLatest in Rx or Kotlin Flows.

  • Related