kkemper
kkemper

Reputation: 317

When is the observer called for live data?

I have a view model that processes an array of bytes into a somewhat complex array of floats. Part of the data is a timestamp which I've setup as a LiveData type and the observer listens for changes in the timestamp. When a change happens, it gets the new timestamp and also gets the array of floats.

My question is when "value" is set in a LiveData object, are the observers immediately called or does it wait for the surrounding function to complete? In other words, should I make sure to update whatever other data the observer is accessing before setting the "value"?

Also, is this abusing the LiveData mechanism (using it as a flag for a larger change in data)?

  val mTime = MutableLiveData<Double>()
  var mStateDataSet = ArrayList<ArrayList<Float>>()

  fun updateData(rawData: ByteArray) {

    val buffer = ByteBuffer.wrap(rawData).order(ByteOrder.LITTLE_ENDIAN)

    val min = (buffer.getInt(4)).toDouble()
    val usec = (buffer.getInt(8)).toDouble()

    val time: Double = min * 60.0 + usec * (1.0 / 1e6)

    // Update the live data....
    mTime.value = time

    // This data is used by the observer of "mTime"
    mStateDataSet[KEY_VOLTAGES] = getSubDataFloat(buffer, NUM_VOLTAGE);
    mStateDataSet[KEY_PRESSURES] = getSubDataFloat(buffer, NUM_PRESSURE);
    mStateDataSet[KEY_LEFT_ANGLES] = getSubDataFloat(buffer, NUM_LEFT_ANGLES);
    mStateDataSet[KEY_RIGHT_ANGLES] = getSubDataFloat(buffer, NUM_RIGHT_ANGLES);
    mStateDataSet[KEY_LEFT_ACCEL] = getSubDataFloat(buffer, NUM_LEFT_ACCEL);
    mStateDataSet[KEY_RIGHT_ACCEL] = getSubDataFloat(buffer, NUM_RIGHT_ACCEL);
    mStateDataSet[KEY_DEBUG] = getSubDataFloat(buffer, NUM_DEBUG);

  }

// Example observer from one of my fragments
    val timeObserver = Observer<Double> { newTime ->
      addDataPoint(mSharedStateDataViewModel.mStateDataSet, newTime)
    }
    mSharedStateDataViewModel.mTime.observe(viewLifecycleOwner, timeObserver)

Upvotes: 2

Views: 1044

Answers (2)

You should update the livedata value with

mTime.postValue(time)

Also, by Tenfour04 comment

postValue will result in the observers being called after this function returns. setValue results in the observers being called before setValue returns, so before the rest of the code in this function.

Upvotes: 3

mightyWOZ
mightyWOZ

Reputation: 8315

Given that the state of the observer's LifeCycleOwner(ie. Activity, Fragment) is at least STARTED and you use the setValue method, the Observer will be notified instantly.

In your case when you do mTime.value = time, this will instantly inform the associated Observer, please note that if you have multiple Observers on the same LiveData object then it may take some time to inform all of them and there may be significant delay between notifications to two different Observers.

If however you use postValue in your example then the Observer will be notified after the enclosing method finishes.

Upvotes: 0

Related Questions