In my ViewModel I have this LiveData
list:
val liveList: LiveData<List<Int>>
In my Activity, at some point I access the data in the list like this:
viewModel.liveList.value?.let { letList ->
while (letList.size < 10)
delay(100)
Some data gets added to liveList
concurrently. (Above snippet doesn't run in the main thread). Will letList
see these updates made to liveList
? Thus, is letList
still connected to liveList
?
Or is letList
a copy of the list in liveList
made at the point in time the let
is executed? Thus, if liveList
happens to have less than 10 elements at this point, the while
loop will never terminate, no matter how many elements are added to liveList
?
CodePudding user response:
Will letList see these updates made to liveList?
Yes, it points to the same object.
Thus, is letList still connected to liveList?
It's not really "connected". It's just a reference to the same object.
Or is letList a copy of the list in liveList made at the point in time the let is executed?
No, it is not a copy.
Thus, if liveList happens to have less than 10 elements at this point, the while loop will never terminate, no matter how many elements are added to liveList?
That could be the case, since the contained list instance itself might have been replaced in the containing LiveData. If the List instance is replaced with a new one inside the LiveData, and that list get changed over time, then the loop will never see a newly sized list since it will be stuck on the original.
Though I question if this is the best approach to the task at hand. Maybe you should set up an observer on the list and do something whenever it's known to change, rather than busy-looping on it.
CodePudding user response:
That code compiles to something like this (I'm going to use Kotlin syntax but you get the idea):
val letList = viewModel.liveList.value
if (letList != null) {
while (letList.size < 10) {
delay(100)
}
}
so letList
is a unique variable which is assigned the current value of viewModel.liveList.value
. That's why running a let
block on a nullable var
is safe - even if the original var could be set to null by another thread, you're working with your own private copy assigned to the original value. You know it's not going to become null after it's been null-checked - in fact it's not going to change at all! Very useful for capturing that snapshot of a value
The other side to this is just what the value of that variable is - it's a reference to a List
object. If something else has a reference to that same List
, if it adds or removes some items, you'll see those changes too - because it's the same list you're both looking at
That's something you need to be careful about - you might want to create your own copy of that list so that this can't happen. You don't necessarily know how that LiveData
is producing list values - is it creating a new List
each time, so every list it pushes is independent? Or is it mutating a single list, and basically pushing the same object every time, acting as both "here's the current list" and "if you have a copy of that list from earlier, it just updated"?
Copying a list could be as simple as theList.toList()
, but it'll be a different List
object containing the same item objects. If those item objects can be mutated (e.g. if they have a var
that can be changed) then wherever that object is referenced, even if it's in completely separate lists, that change will be visible. You have to know what you're working with and what guarantees it gives you