TRY ANDROID DEV

Android アプリ開発のコーディングネタ。あとエンジニアとしての活動

kotlinでSmart cast to xxx is impossible because response.body() is a complex expressionが発生した場合

状況

Retrofitを使った以下のソースコードでスマートキャストできないとエラーが発生した。

    override fun search(word: String): List<NovelIntroduction> {
        val response = searchService.getNovelList(word).execute()
        if (response.isSuccessful && response.body()!=null) {
            return response.body().mapNotNull { r -> NovelIntroductionTranslator().toNovelIntroduction(r) } // <-- Smart cast impossible
        }
    }

発生しているエラー

Smart cast to xxx is impossible because response.body() is a complex expression

response.body()はList? を返却するメソッドだが、if文でnullチェックしてもListにキャストできない。

対応方法

とりあえず!!をつければエラーは消えるのだが、せっかくのkotlinなのにnull pointer exceptionが発生しうる状況は避けたい。
smat castは同じプロパティに対して何回アクセスしても同じ値を返すことが保証されている場合可能らしい。
つまりvarであったらそもそもsmart castできない。

RetrofitのResponseクラスを覗いてみると以下のようにコーディングされていた。

private final @Nullable T body;
・
・
・
  public @Nullable T body() {
    return body;
  }

よく考えたらRetrofitはjavaでコーディングされているのでvalでない。 (javaでいくらfinalがついていてもListであればimmutableにしない限り内容書き換えられるのでたぶんダメ)

ということは一旦response.body()をvalに移し変えてからnullチェックを行えばよい。

if (response.isSuccessful) {
            val body = response.body()
            if (body!= null) return body.mapNotNull { r -> NovelIntroductionTranslator().toNovelIntroduction(r) }
}

これでSmart Castできた。