なつねこメモ

主にプログラミング関連のメモ帳 ♪(✿╹ヮ╹)ノ 書いてあるコードは自己責任でご自由にどうぞ。記事本文の無断転載は禁止です。

Jetpack Compose で Preview が NoClassDefFoundError で表示されない

Android Studio にて、 Jetpack Compose の @Preview アノテーションを使ってプレビューをしたかったのだが、エラーが出て表示されない。

java.lang.NoClassDefFoundError: _layoutlib_/_internal_/kotlinx/datetime/serializers/InstantIso8601Serializer
    at com.natsuneko.catalyst.models.CatalystStatus$$serializer.deserialize(CatalystStatus.kt:13)
    at com.natsuneko.catalyst.models.CatalystStatus$$serializer.deserialize(CatalystStatus.kt:13)
    at _layoutlib_._internal_.kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
    at _layoutlib_._internal_.kotlinx.serialization.json.Json.decodeFromString(Json.kt:149)
    at com.natsuneko.catalyst.models.mocks.MockedCatalystStatus.mocked_delegate$lambda$0(CatalystStatus.kt:93)
    at _layoutlib_._internal_.kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:86)
    at com.natsuneko.catalyst.models.mocks.MockedCatalystStatus$Companion.getMocked(CatalystStatus.kt:8)
    at com.natsuneko.catalyst.ui.parts.TimelineStatusKt.TimelineStatusPreview(TimelineStatus.kt:26)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at androidx.compose.ui.tooling.ComposableInvoker.invokeComposableMethod(ComposableInvoker.jvm.kt:185)
        at 略
Caused by: java.lang.ClassNotFoundException: _layoutlib_._internal_.kotlinx.datetime.serializers.InstantIso8601Serializer
    ... 87 more

どうやらクラスが無いと言われている様子だが、ライブラリも build.gradle.kts で定義しているしなぁ、と考えていたら、依存関係のミスがあった。 具体的には、ライブラリ側では次のような形で依存を定義していた:

// @build.gradle.kts
dependencies {
    // ...

    // Kotlinx Serialization
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")

    // DateTime
    implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.1")
}

そして、 Android プロジェクト側では、次のように定義していた:

# @libs.versions.toml
[libraries]
kotlinx-datetime = { group = "org.jetbrains.kotlinx", name = "kotlinx-datetime", version = "0.7.1" }
kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version = "1.10.0" }
// @build.gradle.kts
dependencies {
    // ... 略

    implementation(libs.kotlinx.datetime)
    implementation(libs.kotlinx.serialization.json)
    implementation(files("../../CatalystSDK/packages/kotlin/build/libs/catalyst-kotlin-0.1.0.jar"))
}

ポイントは org.jetbrans.kotlinx.kotlinx-datetime のバージョン違いで、 kotlinx-datetime の 0.7.0 にて破壊的変更があり、該当クラスが無くなったことが影響している様子。

zenn.dev

なので、解決策としては:

  1. ライブラリ側のバージョンを上げる
  2. Android プロジェクト側のバージョンを下げる

のどちらか。

バージョンを下げるという選択肢はあまりとりたくないので、ライブラリ側のバージョンを上げることで解決する。 といっても、一番の諸悪の根源は jar を直接指定していることが原因な気がする (依存関係が使われない) ので、 git submodule とかで同一リポジトリ内にすべてを含める方が、 Gradle にサブプロジェクトとして認識させられて、解決する気がする......。 ということで、ビルド時/プレビュー時の依存関係のバージョンには気をつけましょう、という記事でした。つらい。