Android - Filter LiveData List based on Selected Item change in ViewModel












1















I have a AndroidViewModel for one of my fragments which contains a LiveData List, and I have another property for selected item of another LiveData List. Below is an example of what I am talking about:



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

...
}


Note: getAllTeams and getAllPlayers returns a RxJava Flowable List, which I then convert to LiveData List via `.toLiveData



Currently, allPlayers represents all the players from all teams. I'd like to make it so that whenever the value of selectedTeam changes, that allPlayers gets filtered down to only display players from the selectedTeam.



What I've tried is to filter allPlayers directly like so:



val allPlayers: LiveData<List<Player>>
get() = repository.getAllPlayers()
.flatMap { list -> Flowable.fromIterable(list)
.filter {
player -> player.team == selectedTeam.value?.team
}
}
.toList()
.toFlowable()
.toLiveData()


But as you may or may not guess, it doesn't update the filter for allPlayers whenever selectedTeam changes.



Is there anyway to dynamically change the filter for allPlayers whenever selectedTeam changes?



EDIT



Thanks to @EpicPandaForce, the final solution I came up with is as followed:



I created this extension method fun <T, R> LiveData<T>.switchMap(func: (T) -> LiveData<R>) = Transformations.switchMap(this, func) to make the code more readable.



I've also created a function in my repository called getAllPlayersFromTeam(team: Team) which, as the function specifies, gets all the players from a team.



Finally this is the end result of my property:



val allPlayersFromSelectedTeam: LiveData<List<Player>>
get() = selectedTeam.switchMap {
repository
.getAllPlayersFromTeam(it)
.toLiveData()
}









share|improve this question

























  • Shouldn't it be selectedTeam.switchMap { selectedTeam -> to get the intended behavior? Btw it looks supernice, I love it.

    – EpicPandaForce
    Jan 3 at 9:24








  • 1





    @EpicPandaForce copy paste fail to Stack Overflow on my part. Have edited.

    – Hayden
    Jan 3 at 12:30
















1















I have a AndroidViewModel for one of my fragments which contains a LiveData List, and I have another property for selected item of another LiveData List. Below is an example of what I am talking about:



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

...
}


Note: getAllTeams and getAllPlayers returns a RxJava Flowable List, which I then convert to LiveData List via `.toLiveData



Currently, allPlayers represents all the players from all teams. I'd like to make it so that whenever the value of selectedTeam changes, that allPlayers gets filtered down to only display players from the selectedTeam.



What I've tried is to filter allPlayers directly like so:



val allPlayers: LiveData<List<Player>>
get() = repository.getAllPlayers()
.flatMap { list -> Flowable.fromIterable(list)
.filter {
player -> player.team == selectedTeam.value?.team
}
}
.toList()
.toFlowable()
.toLiveData()


But as you may or may not guess, it doesn't update the filter for allPlayers whenever selectedTeam changes.



Is there anyway to dynamically change the filter for allPlayers whenever selectedTeam changes?



EDIT



Thanks to @EpicPandaForce, the final solution I came up with is as followed:



I created this extension method fun <T, R> LiveData<T>.switchMap(func: (T) -> LiveData<R>) = Transformations.switchMap(this, func) to make the code more readable.



I've also created a function in my repository called getAllPlayersFromTeam(team: Team) which, as the function specifies, gets all the players from a team.



Finally this is the end result of my property:



val allPlayersFromSelectedTeam: LiveData<List<Player>>
get() = selectedTeam.switchMap {
repository
.getAllPlayersFromTeam(it)
.toLiveData()
}









share|improve this question

























  • Shouldn't it be selectedTeam.switchMap { selectedTeam -> to get the intended behavior? Btw it looks supernice, I love it.

    – EpicPandaForce
    Jan 3 at 9:24








  • 1





    @EpicPandaForce copy paste fail to Stack Overflow on my part. Have edited.

    – Hayden
    Jan 3 at 12:30














1












1








1


1






I have a AndroidViewModel for one of my fragments which contains a LiveData List, and I have another property for selected item of another LiveData List. Below is an example of what I am talking about:



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

...
}


Note: getAllTeams and getAllPlayers returns a RxJava Flowable List, which I then convert to LiveData List via `.toLiveData



Currently, allPlayers represents all the players from all teams. I'd like to make it so that whenever the value of selectedTeam changes, that allPlayers gets filtered down to only display players from the selectedTeam.



What I've tried is to filter allPlayers directly like so:



val allPlayers: LiveData<List<Player>>
get() = repository.getAllPlayers()
.flatMap { list -> Flowable.fromIterable(list)
.filter {
player -> player.team == selectedTeam.value?.team
}
}
.toList()
.toFlowable()
.toLiveData()


But as you may or may not guess, it doesn't update the filter for allPlayers whenever selectedTeam changes.



Is there anyway to dynamically change the filter for allPlayers whenever selectedTeam changes?



EDIT



Thanks to @EpicPandaForce, the final solution I came up with is as followed:



I created this extension method fun <T, R> LiveData<T>.switchMap(func: (T) -> LiveData<R>) = Transformations.switchMap(this, func) to make the code more readable.



I've also created a function in my repository called getAllPlayersFromTeam(team: Team) which, as the function specifies, gets all the players from a team.



Finally this is the end result of my property:



val allPlayersFromSelectedTeam: LiveData<List<Player>>
get() = selectedTeam.switchMap {
repository
.getAllPlayersFromTeam(it)
.toLiveData()
}









share|improve this question
















I have a AndroidViewModel for one of my fragments which contains a LiveData List, and I have another property for selected item of another LiveData List. Below is an example of what I am talking about:



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

...
}


Note: getAllTeams and getAllPlayers returns a RxJava Flowable List, which I then convert to LiveData List via `.toLiveData



Currently, allPlayers represents all the players from all teams. I'd like to make it so that whenever the value of selectedTeam changes, that allPlayers gets filtered down to only display players from the selectedTeam.



What I've tried is to filter allPlayers directly like so:



val allPlayers: LiveData<List<Player>>
get() = repository.getAllPlayers()
.flatMap { list -> Flowable.fromIterable(list)
.filter {
player -> player.team == selectedTeam.value?.team
}
}
.toList()
.toFlowable()
.toLiveData()


But as you may or may not guess, it doesn't update the filter for allPlayers whenever selectedTeam changes.



Is there anyway to dynamically change the filter for allPlayers whenever selectedTeam changes?



EDIT



Thanks to @EpicPandaForce, the final solution I came up with is as followed:



I created this extension method fun <T, R> LiveData<T>.switchMap(func: (T) -> LiveData<R>) = Transformations.switchMap(this, func) to make the code more readable.



I've also created a function in my repository called getAllPlayersFromTeam(team: Team) which, as the function specifies, gets all the players from a team.



Finally this is the end result of my property:



val allPlayersFromSelectedTeam: LiveData<List<Player>>
get() = selectedTeam.switchMap {
repository
.getAllPlayersFromTeam(it)
.toLiveData()
}






android kotlin android-livedata






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 3 at 12:31







Hayden

















asked Jan 1 at 11:09









HaydenHayden

605515




605515













  • Shouldn't it be selectedTeam.switchMap { selectedTeam -> to get the intended behavior? Btw it looks supernice, I love it.

    – EpicPandaForce
    Jan 3 at 9:24








  • 1





    @EpicPandaForce copy paste fail to Stack Overflow on my part. Have edited.

    – Hayden
    Jan 3 at 12:30



















  • Shouldn't it be selectedTeam.switchMap { selectedTeam -> to get the intended behavior? Btw it looks supernice, I love it.

    – EpicPandaForce
    Jan 3 at 9:24








  • 1





    @EpicPandaForce copy paste fail to Stack Overflow on my part. Have edited.

    – Hayden
    Jan 3 at 12:30

















Shouldn't it be selectedTeam.switchMap { selectedTeam -> to get the intended behavior? Btw it looks supernice, I love it.

– EpicPandaForce
Jan 3 at 9:24







Shouldn't it be selectedTeam.switchMap { selectedTeam -> to get the intended behavior? Btw it looks supernice, I love it.

– EpicPandaForce
Jan 3 at 9:24






1




1





@EpicPandaForce copy paste fail to Stack Overflow on my part. Have edited.

– Hayden
Jan 3 at 12:30





@EpicPandaForce copy paste fail to Stack Overflow on my part. Have edited.

– Hayden
Jan 3 at 12:30












1 Answer
1






active

oldest

votes


















2














You need to switchMap over the selectedTeam, and possibly renamed "allPlayers" because that's a lie. :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
}


Which I really hope it works as I wrote it here directly.






share|improve this answer
























  • Thanks for the reply, will try it out when I get home tonight.

    – Hayden
    Jan 1 at 23:56











  • The solution works, thanks. Are you able to if you can explain in more detail on why you need to use two switchMaps for it to work?

    – Hayden
    Jan 2 at 9:44











  • Technically I only need the second switchMap because your repository doesn't seem to be able to provide a repository.getAllPlayersForTeam(team) LiveData. If it did, I wouldn't filter the LiveData and map it over to a new LiveData (with the filtered data set), because I could get that LiveData directly.

    – EpicPandaForce
    Jan 2 at 10:30








  • 1





    I'll look further into adding a function into the repository to do just that, thanks.

    – Hayden
    Jan 2 at 10:36











  • One thing to note is that as you are using Kotlin, you might want to consider something like, fun <T, R> LiveData<T>.switchMap(func: (T) -> LiveData<R>) = Transformations.switchMap(this, func) just for better chaining.

    – EpicPandaForce
    Jan 2 at 10:51













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53994960%2fandroid-filter-livedata-list-based-on-selected-item-change-in-viewmodel%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














You need to switchMap over the selectedTeam, and possibly renamed "allPlayers" because that's a lie. :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
}


Which I really hope it works as I wrote it here directly.






share|improve this answer
























  • Thanks for the reply, will try it out when I get home tonight.

    – Hayden
    Jan 1 at 23:56











  • The solution works, thanks. Are you able to if you can explain in more detail on why you need to use two switchMaps for it to work?

    – Hayden
    Jan 2 at 9:44











  • Technically I only need the second switchMap because your repository doesn't seem to be able to provide a repository.getAllPlayersForTeam(team) LiveData. If it did, I wouldn't filter the LiveData and map it over to a new LiveData (with the filtered data set), because I could get that LiveData directly.

    – EpicPandaForce
    Jan 2 at 10:30








  • 1





    I'll look further into adding a function into the repository to do just that, thanks.

    – Hayden
    Jan 2 at 10:36











  • One thing to note is that as you are using Kotlin, you might want to consider something like, fun <T, R> LiveData<T>.switchMap(func: (T) -> LiveData<R>) = Transformations.switchMap(this, func) just for better chaining.

    – EpicPandaForce
    Jan 2 at 10:51


















2














You need to switchMap over the selectedTeam, and possibly renamed "allPlayers" because that's a lie. :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
}


Which I really hope it works as I wrote it here directly.






share|improve this answer
























  • Thanks for the reply, will try it out when I get home tonight.

    – Hayden
    Jan 1 at 23:56











  • The solution works, thanks. Are you able to if you can explain in more detail on why you need to use two switchMaps for it to work?

    – Hayden
    Jan 2 at 9:44











  • Technically I only need the second switchMap because your repository doesn't seem to be able to provide a repository.getAllPlayersForTeam(team) LiveData. If it did, I wouldn't filter the LiveData and map it over to a new LiveData (with the filtered data set), because I could get that LiveData directly.

    – EpicPandaForce
    Jan 2 at 10:30








  • 1





    I'll look further into adding a function into the repository to do just that, thanks.

    – Hayden
    Jan 2 at 10:36











  • One thing to note is that as you are using Kotlin, you might want to consider something like, fun <T, R> LiveData<T>.switchMap(func: (T) -> LiveData<R>) = Transformations.switchMap(this, func) just for better chaining.

    – EpicPandaForce
    Jan 2 at 10:51
















2












2








2







You need to switchMap over the selectedTeam, and possibly renamed "allPlayers" because that's a lie. :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
}


Which I really hope it works as I wrote it here directly.






share|improve this answer













You need to switchMap over the selectedTeam, and possibly renamed "allPlayers" because that's a lie. :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
}


Which I really hope it works as I wrote it here directly.







share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 1 at 22:28









EpicPandaForceEpicPandaForce

49.4k14132255




49.4k14132255













  • Thanks for the reply, will try it out when I get home tonight.

    – Hayden
    Jan 1 at 23:56











  • The solution works, thanks. Are you able to if you can explain in more detail on why you need to use two switchMaps for it to work?

    – Hayden
    Jan 2 at 9:44











  • Technically I only need the second switchMap because your repository doesn't seem to be able to provide a repository.getAllPlayersForTeam(team) LiveData. If it did, I wouldn't filter the LiveData and map it over to a new LiveData (with the filtered data set), because I could get that LiveData directly.

    – EpicPandaForce
    Jan 2 at 10:30








  • 1





    I'll look further into adding a function into the repository to do just that, thanks.

    – Hayden
    Jan 2 at 10:36











  • One thing to note is that as you are using Kotlin, you might want to consider something like, fun <T, R> LiveData<T>.switchMap(func: (T) -> LiveData<R>) = Transformations.switchMap(this, func) just for better chaining.

    – EpicPandaForce
    Jan 2 at 10:51





















  • Thanks for the reply, will try it out when I get home tonight.

    – Hayden
    Jan 1 at 23:56











  • The solution works, thanks. Are you able to if you can explain in more detail on why you need to use two switchMaps for it to work?

    – Hayden
    Jan 2 at 9:44











  • Technically I only need the second switchMap because your repository doesn't seem to be able to provide a repository.getAllPlayersForTeam(team) LiveData. If it did, I wouldn't filter the LiveData and map it over to a new LiveData (with the filtered data set), because I could get that LiveData directly.

    – EpicPandaForce
    Jan 2 at 10:30








  • 1





    I'll look further into adding a function into the repository to do just that, thanks.

    – Hayden
    Jan 2 at 10:36











  • One thing to note is that as you are using Kotlin, you might want to consider something like, fun <T, R> LiveData<T>.switchMap(func: (T) -> LiveData<R>) = Transformations.switchMap(this, func) just for better chaining.

    – EpicPandaForce
    Jan 2 at 10:51



















Thanks for the reply, will try it out when I get home tonight.

– Hayden
Jan 1 at 23:56





Thanks for the reply, will try it out when I get home tonight.

– Hayden
Jan 1 at 23:56













The solution works, thanks. Are you able to if you can explain in more detail on why you need to use two switchMaps for it to work?

– Hayden
Jan 2 at 9:44





The solution works, thanks. Are you able to if you can explain in more detail on why you need to use two switchMaps for it to work?

– Hayden
Jan 2 at 9:44













Technically I only need the second switchMap because your repository doesn't seem to be able to provide a repository.getAllPlayersForTeam(team) LiveData. If it did, I wouldn't filter the LiveData and map it over to a new LiveData (with the filtered data set), because I could get that LiveData directly.

– EpicPandaForce
Jan 2 at 10:30







Technically I only need the second switchMap because your repository doesn't seem to be able to provide a repository.getAllPlayersForTeam(team) LiveData. If it did, I wouldn't filter the LiveData and map it over to a new LiveData (with the filtered data set), because I could get that LiveData directly.

– EpicPandaForce
Jan 2 at 10:30






1




1





I'll look further into adding a function into the repository to do just that, thanks.

– Hayden
Jan 2 at 10:36





I'll look further into adding a function into the repository to do just that, thanks.

– Hayden
Jan 2 at 10:36













One thing to note is that as you are using Kotlin, you might want to consider something like, fun <T, R> LiveData<T>.switchMap(func: (T) -> LiveData<R>) = Transformations.switchMap(this, func) just for better chaining.

– EpicPandaForce
Jan 2 at 10:51







One thing to note is that as you are using Kotlin, you might want to consider something like, fun <T, R> LiveData<T>.switchMap(func: (T) -> LiveData<R>) = Transformations.switchMap(this, func) just for better chaining.

– EpicPandaForce
Jan 2 at 10:51






















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53994960%2fandroid-filter-livedata-list-based-on-selected-item-change-in-viewmodel%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Monofisismo

Angular Downloading a file using contenturl with Basic Authentication

Olmecas