NonNullとして扱えるAndroid Architecture ComponentsのLiveDataを作る

[Android Architecture Components](https://developer.android.com/jetpack/arch/)の[LiveData](https://developer.android.com/topic/libraries/architecture/livedata)、便利ですよね。
しかしながら（特にKotlinから）使う場合にいつも気になるのが、valueをNonNullとして扱えない点です。
運用上Null非許容として扱っているのにLiveDataをかませるとアンラップする必要があり、フォースアンラップしてもいいのですが精神衛生上良くありません。
なのでLiveDataをちょこっと拡張してNonNullに限定したクラスを作ってみました。

## 1. NonNullなObserverを作る

まずそもそものLiveDataのObserverはJavaでプラットフォーム型で定義されており、これをどうにかしないとNonNullとしては扱えません。
以下がオリジナルのObserverコードです

```java:Observer.java
/**
 * A simple callback that can receive from {@link LiveData}.
 *
 * @param <T> The type of the parameter
 *
 * @see LiveData LiveData - for a usage description.
 */
public interface Observer<T> {
    /**
     * Called when the data is changed.
     * @param t  The new data
     */
    void onChanged(T t);
}
```

なのでNonNullなアノテーションをつけたNonNullObserverを作成します。

```java:NonNullObserver.java
public interface NonNullObserver<T> {
    void onChanged(@NonNull T t);
}
```

ちなみにJavaで書いているのはあえてで、SAM変換を出来るようにして既存のObserverと使い勝手をあわせるためです。
よりKotlinっぽく書きたい場合は独立したインターフェースとして定義せず、`observer: ((T) -> Unit)`とかのブロック構文を使うといいと思います

## 2. lateinitなLiveDataクラスを作る

次に作るのがNonNull…ではなくlateinit版LiveDataです。（LateInit版が不要であればNonNull版とマージしてしまってもよいかと思います）
Kotlinの`lateinit　var`と同じように初期値を入れる前提でNonNullとして扱います。
また初期値を入れる前に取得しようとすると`UninitializedPropertyAccessException()`を発生させるように記述しています

```kotlin:LateInitLiveData.kt
open class LateInitLiveData<T> : LiveData<T>() {

    private val observers = mutableMapOf<NonNullObserver<T>, Observer<T>>()

    @MainThread
    @Deprecated(
        message = "use observe for NonNull.",
        replaceWith = ReplaceWith("observe(owner, NonNullObserver)"),
        level = DeprecationLevel.HIDDEN
    )
    override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
        super.observe(owner, observer)
    }

    @MainThread
    @Deprecated(
        message = "use observeForever for NonNull.",
        replaceWith = ReplaceWith("observeForever(nonNullObserver)"),
        level = DeprecationLevel.HIDDEN
    )
    override fun observeForever(observer: Observer<in T>) {
        super.observeForever(observer)
    }

    @MainThread
    @Deprecated(
        message = "use observe for NonNull.",
        replaceWith = ReplaceWith("removeObserver(nonNullObserver)"),
        level = DeprecationLevel.HIDDEN
    )
    override fun removeObserver(observer: Observer<in T>) {
        super.removeObserver(observer)
    }

    @MainThread
    open fun observe(owner: LifecycleOwner, nonNullObserver: NonNullObserver<T>) {
        val observer = Observer<T> { nonNullObserver.onChanged(it!!) }
        observers[nonNullObserver] = observer
        super.observe(owner, observer)
    }

    @MainThread
    open fun observeForever(nonNullObserver: NonNullObserver<T>) {
        val observer = Observer<T> { nonNullObserver.onChanged(it!!) }
        observers[nonNullObserver] = observer
        super.observeForever(observer)
    }

    @MainThread
    open fun removeObserver(nonNullObserver: NonNullObserver<T>) {
        val observer = observers[nonNullObserver]
        if (observer != null) {
            observers.remove(nonNullObserver)
            super.removeObserver(observer)
        }
    }

    override fun getValue(): T {
        return super.getValue() ?: throw UninitializedPropertyAccessException()
    }

    @MainThread
    public override fun setValue(value: T) {
        super.setValue(value)
    }

    public override fun postValue(value: T) {
        super.postValue(value)
    }

}
```

使用するObserverをNonNullObserverにするにあたり、新たにNonNullObserver用のメソッドを生やしています。
既存のObserverメソッドは紛らわしいので`@Deprecated`扱いにして見えなくしています。このへんはお好みです。
また、既存のObserverとNonNullObserverを紐付けてHashMapでメンバー変数として保持しているのはremoveObserverする際に実際のObserverを取り出すためです。

## 3. NonNullなLiveDataを作る

LateInit版を作ってしまえばNonNull版を作るのは簡単で、コンストラクタでの値代入を必須にするだけです

```kotlin:
open class NonNullLiveData<T>(initialValue: T) : LateInitLiveData<T>() {

    init {
        value = initialValue
    }

}
```

## 使い方

NonNullObserver, LateInitLiveData, NonNullLiveDataを使うことでKotlinのNonNull構文やlateinitに近い形でLiveDataを扱うことが出来ます

```kotlin:MainViewModel.kt
class MainViewModel(application: Application) : AndroidViewModel(application) {

    val title = LateInitLiveData<String>() // or NonNullLiveData<String>("")

    init {
        title.value = "Main!" // Can't insert null
    }

}

```

```kotlin:MainActivity.kt
class MainActivity : AppCompatActivity() {

    private val viewModel by lazy { ViewModelProviders.of(this).get(MainViewModel::class.java) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        viewModel.label.observe(this, NonNullObserver {
            title = it // it is NonNull!
        })
    }
}
```

通常のMutableLiveDataだと常にNonNullかどうかを意識する必要があり、nullセーフに扱うことが出来ませんでしたがNonNullLiveDataを用意してあげることでよりLiveData内ではnullを完全に排除する事ができ、安全にLiveDataが使えるようになります。
Kotlin言語を使うのであればなるべくNonNullに寄せたほうが事故が少ないので、個人的にはNonNullLiveDataを作ってからはそっちを使っており、MutableLiveDataはやむを得ずnull許可の値を受け付けるときだけ使うと行った使い方をしています。

## おまけ（NonNullLiveEvent）

以前「[一度だけ通知するAndroid Architecture ComponentsのLiveDataを作る](https://qiita.com/KazaKago/items/acce0c1a970441b44f39)」というタイトルでLiveEventという自作クラスを紹介したのですが、こちらのクラスも似たようなクラスを作ることでNonNullとして扱うことも出来ます。

```kotlin:NonNullLiveEvent.kt
open class NonNullLiveEvent<T> : LiveData<T>() {

    private val observers = mutableMapOf<NonNullObserver<T>, Observer<T>>()
    private val dispatchedTagSet = mutableSetOf<String>()

    @MainThread
    @Deprecated(
        message = "use observe for NonNull.",
        replaceWith = ReplaceWith("observe(owner, \"\", nonNullObserver)"),
        level = DeprecationLevel.HIDDEN
    )
    override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
        observe(owner, "", NonNullObserver { observer.onChanged(it) })
    }

    @MainThread
    @Deprecated(
        message = "use observeForever for NonNull.",
        replaceWith = ReplaceWith("observeForever(\"\", nonNullObserver)"),
        level = DeprecationLevel.HIDDEN
    )
    override fun observeForever(observer: Observer<in T>) {
        super.observeForever(observer)
    }

    @MainThread
    @Deprecated(
        message = "use observe for NonNull.",
        replaceWith = ReplaceWith("removeObserver(nonNullObserver)"),
        level = DeprecationLevel.HIDDEN
    )
    override fun removeObserver(observer: Observer<in T>) {
        super.removeObserver(observer)
    }

    @MainThread
    @Deprecated(
        message = "should not use getValue() in LiveEvent.",
        level = DeprecationLevel.HIDDEN
    )
    override fun getValue(): T? {
        return super.getValue()
    }

    @MainThread
    open fun observe(owner: LifecycleOwner, tag: String, nonNullObserver: NonNullObserver<T>) {
        val observer = Observer<T> {
            val internalTag = owner::class.java.name + "#" + tag
            if (!dispatchedTagSet.contains(internalTag)) {
                dispatchedTagSet.add(internalTag)
                nonNullObserver.onChanged(it!!)
            }
        }
        observers[nonNullObserver] = observer
        super.observe(owner, observer)
    }

    @MainThread
    open fun observeForever(tag: String, nonNullObserver: NonNullObserver<T>) {
        val observer = Observer<T> {
            if (!dispatchedTagSet.contains(tag)) {
                dispatchedTagSet.add(tag)
                nonNullObserver.onChanged(it!!)
            }
        }
        observers[nonNullObserver] = observer
        super.observeForever(observer)
    }

    @MainThread
    open fun removeObserver(nonNullObserver: NonNullObserver<T>) {
        val observer = observers[nonNullObserver]
        if (observer != null) {
            observers.remove(nonNullObserver)
            super.removeObserver(observer)
        }
    }

    @MainThread
    open fun call(t: T) {
        dispatchedTagSet.clear()
        value = t
    }

}
```

## 参考

[NonNull LiveData with Kotlin extension - ProAndroidDev](https://proandroiddev.com/nonnull-livedata-with-kotlin-extension-26963ffd0333)