我正在尝试实现我正在使用 Room 的分页,我花了很长时间才意识到这一切都为我完成了,但我需要做的是能够过滤搜索并对我的数据进行排序。我想暂时将其保留为 LiveData,以便稍后交换。我有这种过滤搜索和排序的方法,效果很好,
@SuppressLint("DefaultLocale")
private fun searchAndFilterPokemon(): LiveData<List<PokemonWithTypesAndSpecies>> {
return Transformations.switchMap(search) { search ->
val allPokemon = repository.searchPokemonWithTypesAndSpecies(search)
Transformations.switchMap(filters) { filters ->
val pokemon = when {
filters.isNullOrEmpty() -> allPokemon
else -> {
Transformations.switchMap(allPokemon) { pokemonList ->
val filteredList = pokemonList.filter { pokemon ->
pokemon.matches = 0
val filter = filterTypes(pokemon, filters)
filter
}
maybeSortList(filters, filteredList)
}
}
}
pokemon
}
}
}
这里有几个switchmaps,第一个是响应搜索更新
var search: MutableLiveData<String> = getSearchState()
第二个是响应过滤器更新
val filters: MutableLiveData<MutableSet<String>> = getCurrentFiltersState()
第三个是观察搜索到的列表更新,然后调用filterTypes和maybeSortList这两个过滤和排序的小方法
@SuppressLint("DefaultLocale")
private fun filterTypes(
pokemon: PokemonWithTypesAndSpecies,
filters: MutableSet<String>
): Boolean {
var match = false
for (filter in filters) {
for (type in pokemon.types) {
if (type.name.toLowerCase() == filter.toLowerCase()) {
val matches = pokemon.matches.plus(1)
pokemon.apply {
this.matches = matches
}
match = true
}
}
}
return match
}
private fun maybeSortList(
filters: MutableSet<String>,
filteredList: List<PokemonWithTypesAndSpecies>
): MutableLiveData<List<PokemonWithTypesAndSpecies>> {
return if (filters.size > 1)
MutableLiveData(filteredList.sortedByDescending {
Log.d("VM", "SORTING ${it.pokemon.name} ${it.matches}")
it.matches
})
else MutableLiveData(filteredList)
}
如前所述,我想将这些迁移到分页 3 并且很难做到这一点我已经更改了我的存储库和 dao 以返回 PagingSource,我只想更改我的视图模型以将 PagingData 作为实时数据返回,到目前为止我有这个
@SuppressLint("DefaultLocale")
private fun searchAndFilterPokemonPager(): LiveData<PagingData<PokemonWithTypesAndSpecies>> {
val pager = Pager(
config = PagingConfig(
pageSize = 50,
enablePlaceholders = false,
maxSize = 200
)
){
searchAndFilterPokemonWithPaging()
}.liveData.cachedIn(viewModelScope)
Transformations.switchMap(filters){
MutableLiveData<String>()
}
return Transformations.switchMap(search) {search ->
val searchedPokemon =
MutableLiveData<PagingData<PokemonWithTypesAndSpecies>>(pager.value?.filter { it.pokemon.name.contains(search) })
Transformations.switchMap(filters) { filters ->
val pokemon = when {
filters.isNullOrEmpty() -> searchedPokemon
else -> {
Transformations.switchMap(searchedPokemon) { pokemonList ->
val filteredList = pokemonList.filter { pokemon ->
pokemon.matches = 0
val filter = filterTypes(pokemon, filters)
filter
}
maybeSortList(filters, filteredList = filteredList)
}
}
}
pokemon
}
}
}
但是 switchmap 给了我一个错误
Type inference failed: Cannot infer type parameter Y in
fun <X : Any!, Y : Any!> switchMap
(
source: LiveData<X!>,
switchMapFunction: (input: X!) → LiveData<Y!>!
)
我想我理解但不知道如何解决它,过滤器和排序方法也不再起作用,我看不到任何用 PageData 替换它的好方法,它有一个过滤器但没有排序?任何帮助表示赞赏:LiveData<Y!
更新感谢@Shadow,我已经重写它以使用中介实时数据实现搜索,但我仍然坚持过滤
init {
val combinedValues =
MediatorLiveData<Pair<String?, MutableSet<String>?>?>().apply {
addSource(search) {
value = Pair(it, filters.value)
}
addSource(filters) {
value = Pair(search.value, it)
}
}
searchPokemon = Transformations.switchMap(combinedValues) { pair ->
val search = pair?.first
val filters = pair?.second
if (search != null && filters != null) {
searchAndFilterPokemonPager(search)
} else null
}
}
@SuppressLint("DefaultLocale")
private fun searchAndFilterPokemonPager(search: String): LiveData<PagingData<PokemonWithTypesAndSpecies>> {
return Pager(
config = PagingConfig(
pageSize = 50,
enablePlaceholders = false,
maxSize = 200
)
){
searchAllPokemonWithPaging(search)
}.liveData.cachedIn(viewModelScope)
}
@SuppressLint("DefaultLocale")
private fun searchAllPokemonWithPaging(search: String): PagingSource<Int, PokemonWithTypesAndSpecies> {
return repository.searchPokemonWithTypesAndSpeciesWithPaging(search)
}