モジュールを追加しただけで出てくる Duplicate class ... とかいうエラーを調査したが途中で力尽きた
AndroidStudio で[File]->[New]->[New Module]から AndroidLibrary を追加したら急に怒られた時のメモです。
Duplicate class androidx.lifecycle.ViewModelLazy found in modules lifecycle-viewmodel-2.5.1-runtime (androidx.lifecycle:lifecycle-viewmodel:2.5.1) and lifecycle-viewmodel-ktx-2.3.1-runtime (androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1)
Duplicate class androidx.lifecycle.ViewTreeViewModelKt found in modules lifecycle-viewmodel-2.5.1-runtime (androidx.lifecycle:lifecycle-viewmodel:2.5.1) and lifecycle-viewmodel-ktx-2.3.1-runtime (androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1)
Go to the documentation to learn how to Fix dependency resolution errors.
エラーメッセージを読み解く
わかりやすくなるようインデントをつけてみました
// ①
Duplicate class
androidx.lifecycle.ViewModelLazy
found in modules
lifecycle-viewmodel-2.5.1-runtime
(androidx.lifecycle:lifecycle-viewmodel:2.5.1)
and
lifecycle-viewmodel-ktx-2.3.1-runtime
(androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1)
// ②
Duplicate class
androidx.lifecycle.ViewTreeViewModelKt
found in modules
lifecycle-viewmodel-2.5.1-runtime
(androidx.lifecycle:lifecycle-viewmodel:2.5.1)
and
lifecycle-viewmodel-ktx-2.3.1-runtime
(androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1)
どうやらViewModelLazy
というクラス名のクラスが二つのモジュール間(androidx.lifecycle:lifecycle-viewmodel
とandroidx.lifecycle:lifecycle-viewmodel-ktx
)で競合してしまってるようです。
(ViewTreeViewModelKt
も同様)
ネットでググる
Specify both to enforce the latest version for all dependencies:
def lifecycle_version = "2.4.0" implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
両方を指定すると、すべての依存関係に最新バージョンを強制的に適用します。
クラス名が競合する的なこと言われてるのにどっちも指定するとエラーが出ない?なぜだ....
納得がいかなかったので自分で独自にエラー解決方法を探ってみることにしました
追加したモジュールの build.gradle を見る
エラーメッセージ中に出てたモジュールを見て 「そんなモジュールは追加した覚えがないぞ!」 と思ったので、追加したモジュールの build.gradle を見に行きました。
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.7.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
}
↑↑↑ をご覧の通り、androidx.lifecycle:lifecycle-viewmodel
とandroidx.lifecycle:lifecycle-viewmodel-ktx
とかいうモジュールは依存関係に追加していません。
ということは上記ライブラリがandroidx.lifecycle:lifecycle-viewmodel-ktx
とかのライブラリに依存している可能性が高いので、これらどれかのモジュールをdependencies
から外したら通るんじゃね?ということで一つづつ検証してみました。
検証 1 implementation 'androidx.core:core-ktx:1.7.0'を除外
androidx.core:core-ktx
は元々あるモジュール(app モジュール)にも dependencies に記述が(デフォルトで)あったのでこれはあまり関係ないとは思いながら念の為検証してみました。
dependencies {
// implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.7.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
}
変わらず...
検証 2 implementation 'androidx.appcompat:appcompat:1.5.1'を除外
appcompat
を使った開発経験がほぼ 0 なのですが、なんか ViewModel とか中に入ってそうな感じがしていました。
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
// implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.7.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
}
が変わらず...
検証 3 implementation 'com.google.android.material:material:1.7.0'を除外
material
ってあるくらいだから AndroidView とかでマテリアルデザインを扱うためのライブラリなのかな?知らんけど。
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.5.1'
// implementation 'com.google.android.material:material:1.7.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
}
ダメでした...
検証 4 テスト系のモジュールを除外
そもそもテスト系のモジュールは実行時に走るわけじゃないから関係ない気がしますが念の為検証...
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.7.0'
// testImplementation 'junit:junit:4.13.2'
// androidTestImplementation 'androidx.test.ext:junit:1.1.4'
// androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
}
そりゃそうか......
あれ、もう検証できることは仕切った気がするが......
検証 5 怪しい 2 モジュールを除外
前述の通りappcompat
とmaterial
は自分の知識不足も相まって不信感が止まなかったのでその二つを除外してみることにしました。
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
// implementation 'androidx.appcompat:appcompat:1.5.1'
// implementation 'com.google.android.material:material:1.7.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
}
すると......
ビルド通ったぁぁぁぁぁ!
結局原因は何だったんだろう...
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.7.0'
今回除外することでエラーが解決したこの 2 行はモジュール作成時にデフォルトで入ってた記述なので、以下のようにこれら二つの中で同じクラス(androidx.lifecycle.ViewModelLazy
)などが入っていたとは考えにくいです。
この状況は考えにくい...
ここで発想を変えました。
今回作ったプロジェクトはJetpackCompose
で開発していました。
Compose でプロジェクトを作ると以下のような記述がapp
モジュールの build.gradle にデフォルトで含まれています。
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
おそらくこれと'androidx.appcompat:appcompat:1.5.1'や'com.google.android.material:material:1.7.0'に入っているViewModelLazy
クラスが競合したのではないか、と思っています。
もうこれ以上モジュールの依存関係を探るのがめんどい
私のデバッグ力ではこれが限界です。有識者の方、私に知恵をお授けください。(他力本願)
Discussion
とりあえず、version catalogを使おう