2

In my mind, Kotlin is null safe.

The Code A is from the project Universal Android Music Player Sample, you can see here

It seems that val rootMediaId: LiveData<String> is not null safe in Code A, a null string can be assigned to rootMediaId, I don't know why Android Studio can compile these code, could you tell me?

I think that the Code B is reputable code.

Code A

viewModel.rootMediaId.observe(this,
                Observer<String> { rootMediaId ->
                    if (rootMediaId != null) {
                        navigateToMediaItem(rootMediaId)
                    }
                })



class MainActivityViewModel(
    private val musicServiceConnection: MusicServiceConnection
) : ViewModel() {

    val rootMediaId: LiveData<String> =
        Transformations.map(musicServiceConnection.isConnected) { isConnected ->
            if (isConnected) {
                musicServiceConnection.rootMediaId
            } else {
                null
            }
        }
   ...
}

Code B

class MainActivityViewModel(
    private val musicServiceConnection: MusicServiceConnection
) : ViewModel() {

    val rootMediaId: LiveData<String?> =
        Transformations.map(musicServiceConnection.isConnected) { isConnected ->
            if (isConnected) {
                musicServiceConnection.rootMediaId
            } else {
                null
            }
        }
   ...
}
HelloCW
  • 843
  • 22
  • 125
  • 310
  • Java Platform Types in Kotlin are ***not null-safe, by design***. It's unfortunate, I'd prefer to write `!` to force-unwrap them. – EpicPandaForce May 28 '20 at 07:08

2 Answers2

7

It's because Live Data is written in Java so Kotlin uses platform type here. You can read more about it here. In two words: Java types don't contain nullability information so Kolin cannot infer the correct type. String from Java can be String or String? in Kotlin. Android studio marks such String types as String! so you can pay attention and set appropriate type by yourself.

Andrei Tanana
  • 7,932
  • 1
  • 27
  • 36
1

Andrei Tanana's answer describes the general situation. But specifically for LiveData, note that getValue() (or value in Kotlin) is nullable and so typed as T? in Kotlin. So in a sense it doesn't matter whether the result is typed as LiveData<String> or LiveData<String?>; the values you get from it are String? either way.

This question also states Observer takes T?, but this doesn't seem to be reflected in the documentation.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487