前人未踏の領域へ Androidアプリ開発編

Androidアプリ開発に関する調査メモ置き場。古い記事にはアプリ以外も含まれます。

Android: Kotlin1.5でkotlin.runCatching内でResultを使った際にClassCastExceptionが発生した

課題

APIのレスポンスを処理する際にkotlin.runCatchingを用いて結果をLiveData<Result>に格納しているが、
まれにkotlin.runCatchingのブロック内で戻り値とは別にLiveDataにResultをセットすることがあった。

 private val _hoge: MutableLiveData<Result<Hoge>> by lazy {
     MutableLiveData()
 }

 private val _fuga: MutableLiveData<Result<Fuga>> by lazy {
     MutableLiveData()
 }

 fun getX() {
    _hoge.value = kotlin.runCaching {
          
           _fuga.value = Result.success(Fuga())      
 
          Hoge()
    }
}

これまでは問題なく動作していたが、Kotlinを1.5にしてAndroid Studioを現時点の最新にしていたところ、どこかの時点でClassCastExceptionが発生するようになった。

対応

Kotlinのバグか仕様変更か分からないけれど、これまで動作していたコードが動かなくなったのは事実なので、とりあえずrunCatchingブロック内で Resultをセットするのをやめることに。

 fun getX() {

    _fuga.value = Result.success(Fuga())

    _hoge.value = kotlin.runCaching {
          Hoge()
    }

}

ちなみに、これがどちらも _fuga.value (同じ代入先)だった場合にはブロックを分けてもエラーになった。この場合はメソッドを分けてしまった方が良いだろう。

コードをよくよく見直すとResultにする必要もない箇所もあったので、リファクタ観点では良かったのかも。

そのうち修正されるかもしれないが、そもそも
runCatching処理内でResultが別途発生するのもおかしいと思うので実装側で対応するのは間違いでもない気がする。

参考

github.com

https://youtrack.jetbrains.com/issue/KT-27105