90

How I can initialize MutableLiveData with initial value? I'm looking for something like:

val text = MutableLiveData<String>("initial value")

Francis
  • 6,788
  • 5
  • 47
  • 64

8 Answers8

108

MutableLiveData has been updated and now it has a constructor that accepts an initial value :)

From what I can see, the constructor is available starting from this version:

implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0-alpha01'

It's a shame they haven't updated MediatorLiveData to reflect that, though.

Edit: they finally did it! MediatorLiveData has a constructor that accepts an initial value as well starting from 2.6.0!


2.1.0 is finally stable, so now you can actually see the new constructor in the documentation.

Fred Porciúncula
  • 8,533
  • 3
  • 40
  • 57
  • 5
    Is this still correct? Looking at the docs, I don't see a public constructor that accepts any arguments: https://developer.android.com/reference/android/arch/lifecycle/MutableLiveData – Noel May 07 '19 at 18:18
  • 1
    @Noel This change isn't included in the stable version, that's why you don't see it there. If you add the dependency and open the class you'll see the new constructor. – Fred Porciúncula Jun 12 '19 at 13:03
  • 1
    I don't think this is valid anymore. 2.1.0-alpha01 version for me does not give me another constructor – Klitos G. Sep 23 '19 at 14:50
  • 2
    @KlitosG. [`2.1.0` is now finally stable](https://developer.android.com/jetpack/androidx/releases/arch#2.1.0), so you can actually see the constructor in the docs now: https://developer.android.com/reference/androidx/lifecycle/MutableLiveData.html#MutableLiveData(T) – Fred Porciúncula Sep 23 '19 at 16:39
  • @FredPorciúncula thanks, you are correct. Some dependency tree problem was making my gradle download version 2.0.0 regardless of me explicitly asking for 2.1.0 – Klitos G. Sep 24 '19 at 10:06
  • Is there a not-nullable version of `MutableLiveData` with this update? – Aykhan Hagverdili Jun 21 '20 at 13:41
  • 1
    @_Static_assert Nope, but there's a lint check called `NonNullableMutableLiveData` (it's actually been mentioned in a fix for the [latest release](https://developer.android.com/jetpack/androidx/releases/lifecycle#version_230_2)), and it's also not really hard to write one yourself: ``` class NonNullableLiveData(initialValue: T) : MutableLiveData(initialValue) { override fun getValue(): T = super.getValue()!! } ``` – Fred Porciúncula Jun 22 '20 at 08:10
55

You can create a handy Extension Function that does the initialization for you.

fun <T : Any?> MutableLiveData<T>.default(initialValue: T) = apply { setValue(initialValue) }

val liveData = MutableLiveData<String>().default("Initial value!")
Lionel Briand
  • 1,732
  • 2
  • 13
  • 21
  • 4
    You could also create a semi-constructor `fun MutableLiveData(initialValue: T) = MutableLiveData().apply { postValue(initialValue) }` to make it more convenient (use `setValue` when you are certain this method will only be called from the main thread) – Mibac Feb 02 '19 at 13:05
  • 1
    I was using this extension function for a while and today I changed it to `fun > LD.default(initialValue: T) = apply { setValue(initialValue) }` to enable it's use on any class extending `MutableLiveData`, e.g. `MediatorLiveData`. – Bojan P. Jul 08 '19 at 07:09
45

UPDATE: Nowadays I would use MutableStateFlow instead of MutableLiveData with initial value.

https://developer.android.com/kotlin/flow/stateflow-and-sharedflow


Finally, I realize that I can use

val text = MutableLiveData<String>().apply { postValue("initial value")}

(postValue is necessary when using from a background thread, otherwise when using from the main thread you can safely use value = "initial value")

Francis
  • 6,788
  • 5
  • 47
  • 64
  • 8
    You can use setValue in a ViewModel. –  Nov 30 '18 at 11:58
  • 1
    This is not the same as setting an initial value. you can easily create a race condition if you are doing this from a worker thread. Reading the value right after the postValue(...) is not guaranteed to give you the posted value, since the setValue(...) will run on a different thread – Klitos G. Sep 23 '19 at 13:36
16

Though this is a Kotlin question, I though it might be helpful if I put the Java version for this as well.

While using androidx dependency:

implementation "androidx.lifecycle:lifecycle-viewmodel:2.1.0"

Initialize the MutableLiveData using the constructor as follows.

new MutableLiveData<>("Initial value");

While using the android dependency:

implementation 'android.arch.lifecycle:viewmodel:1.1.1'

Initialize as follows.

MutableLiveData<String> text = MutableLiveData<String>();
text.setValue("Initial value");

The androidx dependency does have the constructor that takes a value for the initialization of your LiveData. However, if you are using the android dependency you will not have that option of doing the initialization using the constructor.

Reaz Murshed
  • 23,691
  • 13
  • 78
  • 98
3

You can create an extension constructor (sugar trick) like this:

fun <T : Any?> MutableLiveData(defaultValue: T) = MutableLiveData<T>().apply { setValue(defaultValue) }

Using:

var defaultValue: MutableLiveData<String> = MutableLiveData("Default value")
Mickael Belhassen
  • 2,970
  • 1
  • 25
  • 46
2

Also this way..

    val data = MutableLiveData<String>()
    data.value = "data"
    val text = MutableLiveData<String>().apply {
        "apply"
    }
    Log.d("Data",text.value)
2

I have a better solution if you want some default value to be passed in your MutableLiveData<T> If you are using kotlin then there is a class called ObservableProperty<T> which can help you pass the default for your MutableLiveData.Here's my implementation.

val nameLiveData = MutableLiveData<String>()
var name: String by Delegates.observable("") { _, _, newValue ->
    nameLiveData.postValue(newValue)
}

In your Activity or Fragment observe this property.

viewModel.nameLiveData.observe(this, Observer {
        //Your logic goes here
    })

All you have to do change the value is do name = "Joe" and it will posted in your LiveData

pratham kesarkar
  • 3,770
  • 3
  • 19
  • 29
0

I would do like this:

val text by lazy { MutableLiveData<String>("Initial text") }

This way, you are using lazy from kotlin and setting the default value. or even shorter like this:

val text by lazy { MutableLiveData<>("Initial text") }
Amin Keshavarzian
  • 3,646
  • 1
  • 37
  • 38