Fixed
Status Update
Comments
il...@google.com <il...@google.com>
ap...@google.com <ap...@google.com> #2
Yigit, do you have time to fix it?
reemission of the same liveData is racy
reemission of the same liveData is racy
re...@infinum.com <re...@infinum.com> #4
Thanks for the detailed analysis. This may not be an issue anymore since we've started using Main.immediate there but I' not sure; I'll try to create a test case.
il...@google.com <il...@google.com> #5
just emitting same live data reproduces the issue.
@Test
fun raceTest() {
val subLiveData = MutableLiveData(1)
val subject = liveData(testScope.coroutineContext) {
emitSource(subLiveData)
emitSource(subLiveData) //crashes
}
subject.addObserver().apply {
testScope.advanceUntilIdle()
}
}
@Test
fun raceTest() {
val subLiveData = MutableLiveData(1)
val subject = liveData(testScope.coroutineContext) {
emitSource(subLiveData)
emitSource(subLiveData) //crashes
}
subject.addObserver().apply {
testScope.advanceUntilIdle()
}
}
Description
Version used:1.3.0-alpha06
Devices/Android versions reproduced on: Nexus 5 / 8.1.0
It seams that setFragmentResultListener and clearFragment ResultListener on FragmentManager are not working properly or at least are not working as expected.
Basically once the listener is set is not possible to change or clear it.
I think that's because they are just removing or overwriting the key on mResultListeners dictionary, but it's not removing the observer in the LifecycleOwner. The observer is called anyway.
So it's not possible to change the listener once is set.
There are workarounds, but I think is an important bug of this component.
I've created a simple example project to show that.
That's the relevant part:
private fun openEditFragment(teamId: Int) {
println("asking name for team $teamId")
this.setFragmentResultListener(TeamDefinitionFragment.REQ_TEAM) { resultKey: String, bundle: Bundle ->
if (resultKey == TeamDefinitionFragment.REQ_TEAM) {
this.clearFragmentResultListener(TeamDefinitionFragment.REQ_TEAM) //this has no effect
bundle.getString(TeamDefinitionFragment.RESULT_TEAM_NAME)?.let { teamName ->
println("'$teamName' received for team $teamId")
putName(teamId, teamName)
}
}
this.clearFragmentResultListener(TeamDefinitionFragment.REQ_TEAM) //this has no effect neither, that's more weird
}
findNavController().navigate(R.id.action_main_dest_to_definition_dest)
}
Hope I explained myself good enough.