Android - Filter LiveData List based on Selected Item change in ViewModel
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
add a comment |
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
Shouldn't it beselectedTeam.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
add a comment |
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
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
android kotlin android-livedata
edited Jan 3 at 12:31
Hayden
asked Jan 1 at 11:09
HaydenHayden
605515
605515
Shouldn't it beselectedTeam.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
add a comment |
Shouldn't it beselectedTeam.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
add a comment |
1 Answer
1
active
oldest
votes
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.
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 arepository.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
|
show 1 more comment
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
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 arepository.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
|
show 1 more comment
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.
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 arepository.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
|
show 1 more comment
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.
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.
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 arepository.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
|
show 1 more comment
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 arepository.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
|
show 1 more comment
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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