1

In the following example I want to expose a List of Int like this:

    val test: LiveData<List<Int>>
        get() = _test as LiveData<List<Int>>

    private var _test = MutableLiveData(mutableListOf<Int>())

or in another flavor:

    private var _test2 = MutableLiveData(mutableListOf<Int>())
    val test2 = _test2 as LiveData<List<Int>>

Both are working, but there is always an Unchecked Cast.

Unchecked cast: MutableLiveData<MutableList<Int>!> to LiveData<List<Int>>

Is there a better way of doing this?


Just to clarify:

By using emptyList the usage could look like this:

class MainViewModel : ViewModel() {
    val test: LiveData<List<Int>> get() = _test
    private var _test = MutableLiveData(emptyList<Int>())

    init {
        val myPrivateList = mutableListOf<Int>()
        myPrivateList.add(10)
        myPrivateList.add(20)

        _test.value = myPrivateList
    }
}

I was hoping to find a way to do this without an extra list (myPrivateList), something like this:

class MainViewModel : ViewModel() {
    val test: LiveData<List<Int>> get() = _test
    private var _test = MutableLiveData(emptyList<Int>())

    init {
        _test.value?.apply {
            add(1)
            add(2)
            add(3)
        }
    }
}
Awa Kenzo
  • 13
  • 4

2 Answers2

6

You can use emptyList<Int>() or listOf<Int>() to create the MutableLiveData avoiding the unchecked cast:

val test: LiveData<List<Int>> get() = _test
private var _test = MutableLiveData(emptyList<Int>())

If your code was just a sample of your real use case, remember you can always use .toList() on your MutableList.

Giorgio Antonioli
  • 15,771
  • 10
  • 45
  • 70
  • Thanks. Basically **_test** becomes the same type as **test** -> LiveData> I was hoping to solve it without an "extra" list (myPrivateList). – Awa Kenzo Apr 05 '20 at 18:08
1

I know I'm super late with my answer and it's not exactly the answer for this specific question with mutableListOf to List cast. Nevertheless, hopefully, it'll be useful for someone searching for the answer of how to expose MutableLiveData as LiveData from now on.

Just define this tricky Kotlin extension in your BaseViewModel (if you don't have one, you can make it private and define in the ViewModel, where you need to use it):

protected val <T> LiveData<T>.mutable: MutableLiveData<T>
    get() = this as MutableLiveData<T>

Now, when you create your LiveData object, define it the following way:

val liveData: LiveData<Int> = MutableLiveData()

So now you'll be able to access mutable LiveData in your ViewModel nicely and easily:

liveData.mutable.postValue(1)

while your Observers will see the object as LiveData<> and won't have access to .mutable extension, as it is only accessible inside ViewModels.

No private _ LiveData, no duplicating of LiveData objects. Everything is clear and easy-to-use.