Home > Blockchain >  Does `let` make a copy of the data?
Does `let` make a copy of the data?

Time:06-15

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

  • Related