Home > Enterprise >  What is the difference between LiveData<String>() and LiveData<String?>()
What is the difference between LiveData<String>() and LiveData<String?>()

Time:10-27

I am new to LiveData thing in general and I am having a hard time understanding the difference between LiveData<String>() and LiveData<String?>(). I used them interchangeably and nothing seams to break. I know that LiveData.getValue() is marked with @Nullable in Java, so we end up getting String? anyway. So what makes LiveData<String?>() different from LiveData<String>()?

CodePudding user response:

LiveData<String?>() meens that livedata can store null, read please this article to be fully informed: https://kotlinlang.org/docs/null-safety.html

CodePudding user response:

This ended up a bit long but I hope it covers everything!

A LiveData is meant to be observed. The observer receives data, and the LiveData's type says what type that data is. A LiveData<String> will only supply non-null Strings to its observers. A LiveData<String?> can supply Strings and nulls.

Which of those you want depends on what you're doing! Do you need to supply nulls, e.g. for some kind of missing value or whatever? Should they be part of your data? If not, like in any other situation, avoid making the type nullable unless it needs to be.


When an observer first observes a LiveData, it receives the current value. That way it can immediately handle the current data, update to display the current state, etc. But it's possible for a LiveData to have no value initially:

// non-null
val liveDataWithValue = MutableLiveData<String>("hi")
val emptyLiveData = MutableLiveData<String>()

// nullable
val nullableLiveDataWithValue = MutableLiveData<String?>(null)
val emptyNullableLiveData = MutableLiveData<String?>()

The first one there has an initial value. If you observe it, and that value hasn't been updated, the observer will immediately be called with "hi" for its parameter.

The second one has no value. If you observe that, the observer won't be called until a value is set on it. This is useful when you don't actually have any initial data - you can still set up your observer, and nothing will happen until some data is actually pushed.

The third one is the same as the first - it's a nullable String? but with a value of null. That's still a value so if you observe it, the observer will immediately be called with that null. It's still a piece of data your observer has to react to and process.

The last one is nullable but with no initial value. Like the second one, this means there's nothing for the observer to receive at first - but when it does have a value set on it, it could be a null. null is just another kind of value!


But if you go poking around at the LiveData's value property, instead of interacting with it through observe, then that no value state is represented internally by null. Java (or at least the version Android targets) doesn't really have a representation of no value separate from null, so that's just how they have to do things. It just doesn't publish anything until you explicitly set a value on it.

So for each of these:

val emptyLiveData = MutableLiveData<String>()
val nullableLiveDataWithValue = MutableLiveData<String?>(null)
val emptyNullableLiveData = MutableLiveData<String?>()

if you read their value in this state, it will be null for all of them. One explicitly has a value of null set on it, the others are both empty. This also means that even though emptyLiveData's type is non-null, its value property can be null, just because of this "can be empty" situation which is true for all LiveData objects. The nullability of the type is purely about what gets passed to observers.

You generally shouldn't be reading value anyway, except internally (wherever you're actually setting the value). Everything else should be interacting with that LiveData by observing it and reacting to the values that are published, and those values will be whatever type (nullable or not) that you specified

  • Related