Kotlin mutable live data: Remain updated (pun intended)

With Kotlin getting more popular and established, it has become a programming language worthy of note, and it seems to be here to stay. Kotlin’s simple and convenient syntax accelerates development time, and because it’s “not nullable by default”, it reduces crashes and errors.

Data-binding in Kotlin using MutableLiveData potentially opens up a portal to using the outdated value if race conditions are not avoided. This vulnerability can only be introduced by the incorrect method of updating the value or state being used.

The idea is that the view gets its values in real time from the ViewModel. And the ViewModel can use the exact same values during computation.

A word of advice is always to consider the thread you’re working with. Consider the code below:

				
					val value1 = MutableLiveData<Int>(0)
   val value2 = MutableLiveData<Int>(0)
   val total = MutableLiveData<Int>(0)


   fun updateTotal() {
       if (value1.value != null && value2.value != null) {
           value1.postValue(value1.value!! + 1)
           value2.postValue(value2.value!! + 1)
           total.postValue(value1.value!! + value2.value!!)
       }
   }

				
			

Let’s say the above function is called three times. On the third invocation, total could be 4 instead of the expected 6. This will depend on the thread it was invoked from. 

When updating mutable live data values, we either use setValue() or postValue(). It is important to note that setValue() is intended for the main thread, whereas postValue() is meant for background threads.

The Android Developer docs have a section on this, explaining the setValue() and postValue() methods. Link: MutableLiveData | Android Developers.

Calling setValue() from, say, a network thread causes an IllegalStateException, and calling postValue() from the main thread is allowed but not advised as it takes longer to update the value.

Potential issues

Incorrect use of these concepts may result in errors and inconsistent behaviour within apps. As trivial as it seems, these ripple effects can be disastrous. Let’s look at a few potential issues:

  1. Race conditions
  • Using observers on mutable live data could cause this, especially if the observers trigger behaviour based on the value change and expect other values to have been updated.
  1. Incorrect data
  • Some inter-dependent calculations could be obsolete or incorrect without an expected update. As in the above scenario, if after being invoked three times total is 4, then the code after that uses that total value will be affected.
  1. Errors and possible crashes
  • A race condition could eventually culminate in an error or crash caused by incorrect or unavailable data.
  1. Slow performance
  • As mentioned, calling postValue() from the main thread performs slower than setValue() within the main thread. This could lead to the UI taking time to update or just slowing down computational operations.

Conclusion

Using mutable live data within a data binding project produces a well-performing and smooth app when applied correctly. It is also imperative not to fall in the trap of relying on postValue() for everything since it’s allowed by all threads. We have to be as specific as possible to be as accurate and as fast as possible.

This could be the proverbial last straw that broke the camel’s back. So as minor as it seems, it can cause serious damage, especially when working with numbers. As developers, it’s beneficial for us to train our minds to be miniature compilers, so we can detect such issues as we write the code and not during testing or debugging. 

Planning to build an app? 

Try our free software development calculator to maximise your ROI.

Request for Access to Information

The following forms are available to download with regards to request for access to information:

REQUEST FOR ACCESS TO RECORD

OUTCOME OF REQUEST AND OF FEES PAYABLE

INTERNAL APPEAL FORM