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()

    ...
}

注意: getAllTeamsgetAllPlayers 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 
    }

我真的希望它能像我直接写在这里那样工作。