Android - 根据 ViewModel 中所选项目的变化过滤 LiveData 列表
Android - Filter LiveData List based on Selected Item change in ViewModel
我的一个片段有一个 AndroidViewModel,其中包含一个 LiveData 列表,我还有另一个 属性 用于另一个 LiveData 列表的选定项目。下面是我正在谈论的例子:
class TeamViewModel(app: Application): AndroidViewMode(app) {
...
val selectedTeam = MutableLiveData<Team>()
val allTeams: LiveData<List<Team>>
get() = repository.getAllTeams().toLiveData()
val allPlayers: LiveData<List<Player>>
get() = repository.getAllPlayers().toLiveData()
...
}
注意: getAllTeams
和 getAllPlayers
returns 一个 RxJava Flowable List,然后我将其转换为 LiveData List通过 .toLiveData
目前,allPlayers
代表所有球队的所有球员。我想这样做,以便每当 selectedTeam
的值发生变化时,allPlayers
就会被过滤掉以仅显示来自 selectedTeam
.
的玩家
我试过的是像这样直接过滤 allPlayers
:
val allPlayers: LiveData<List<Player>>
get() = repository.getAllPlayers()
.flatMap { list -> Flowable.fromIterable(list)
.filter {
player -> player.team == selectedTeam.value?.team
}
}
.toList()
.toFlowable()
.toLiveData()
但是您可能猜到也可能猜不到,只要 selectedTeam
发生变化,它就不会更新 allPlayers
的过滤器。
是否可以在 selectedTeam
更改时动态更改 allPlayers
的过滤器?
编辑
感谢@EpicPandaForce,我最终得出的解决方案如下:
我创建了这个扩展方法:
fun <T, R> LiveData<T>.switchMap(func: (T) -> LiveData<R>) = Transformations.switchMap(this, func)
使代码更具可读性。
我还在我的存储库中创建了一个名为 getAllPlayersFromTeam(team: Team)
的函数,正如该函数指定的那样,它从一个团队中获取所有球员。
最后这是我的 属性:
的最终结果
val allPlayersFromSelectedTeam: LiveData<List<Player>>
get() = selectedTeam.switchMap {
repository
.getAllPlayersFromTeam(it)
.toLiveData()
}
您需要 switchMap
覆盖 selectedTeam
,并可能重命名 "allPlayers",因为那是谎言。 :P
val selectedTeam = MutableLiveData<Team>()
val allTeams: LiveData<List<Team>>
get() = repository.getAllTeams().toLiveData()
val playersOfSelectedTeam: LiveData<List<Player>>
get() = Transformations.switchMap(selectedTeam) { team ->
val allPlayers = repository.getAllPlayers().toLiveData()
val players = when {
team == null -> allPlayers
else -> {
Transformations.switchMap(allPlayers) { playerList ->
val filteredPlayers = MutableLiveData<List<Player>>()
val filteredList = playerList.filter { player -> player.team == team }
filteredPlayers.value = filteredList
filteredPlayers
}
}
}
players
}
我真的希望它能像我直接写在这里那样工作。
我的一个片段有一个 AndroidViewModel,其中包含一个 LiveData 列表,我还有另一个 属性 用于另一个 LiveData 列表的选定项目。下面是我正在谈论的例子:
class TeamViewModel(app: Application): AndroidViewMode(app) {
...
val selectedTeam = MutableLiveData<Team>()
val allTeams: LiveData<List<Team>>
get() = repository.getAllTeams().toLiveData()
val allPlayers: LiveData<List<Player>>
get() = repository.getAllPlayers().toLiveData()
...
}
注意: getAllTeams
和 getAllPlayers
returns 一个 RxJava Flowable List,然后我将其转换为 LiveData List通过 .toLiveData
目前,allPlayers
代表所有球队的所有球员。我想这样做,以便每当 selectedTeam
的值发生变化时,allPlayers
就会被过滤掉以仅显示来自 selectedTeam
.
我试过的是像这样直接过滤 allPlayers
:
val allPlayers: LiveData<List<Player>>
get() = repository.getAllPlayers()
.flatMap { list -> Flowable.fromIterable(list)
.filter {
player -> player.team == selectedTeam.value?.team
}
}
.toList()
.toFlowable()
.toLiveData()
但是您可能猜到也可能猜不到,只要 selectedTeam
发生变化,它就不会更新 allPlayers
的过滤器。
是否可以在 selectedTeam
更改时动态更改 allPlayers
的过滤器?
编辑
感谢@EpicPandaForce,我最终得出的解决方案如下:
我创建了这个扩展方法:
fun <T, R> LiveData<T>.switchMap(func: (T) -> LiveData<R>) = Transformations.switchMap(this, func)
使代码更具可读性。
我还在我的存储库中创建了一个名为 getAllPlayersFromTeam(team: Team)
的函数,正如该函数指定的那样,它从一个团队中获取所有球员。
最后这是我的 属性:
的最终结果val allPlayersFromSelectedTeam: LiveData<List<Player>>
get() = selectedTeam.switchMap {
repository
.getAllPlayersFromTeam(it)
.toLiveData()
}
您需要 switchMap
覆盖 selectedTeam
,并可能重命名 "allPlayers",因为那是谎言。 :P
val selectedTeam = MutableLiveData<Team>()
val allTeams: LiveData<List<Team>>
get() = repository.getAllTeams().toLiveData()
val playersOfSelectedTeam: LiveData<List<Player>>
get() = Transformations.switchMap(selectedTeam) { team ->
val allPlayers = repository.getAllPlayers().toLiveData()
val players = when {
team == null -> allPlayers
else -> {
Transformations.switchMap(allPlayers) { playerList ->
val filteredPlayers = MutableLiveData<List<Player>>()
val filteredList = playerList.filter { player -> player.team == team }
filteredPlayers.value = filteredList
filteredPlayers
}
}
}
players
}
我真的希望它能像我直接写在这里那样工作。