🤯

モジュールを追加しただけで出てくる Duplicate class ... とかいうエラーを調査したが途中で力尽きた

2023/01/07に公開
1

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-viewmodelandroidx.lifecycle:lifecycle-viewmodel-ktx)で競合してしまってるようです。
(ViewTreeViewModelKtも同様)

ネットでググる

https://stackoverflow.com/questions/69817925/problem-duplicate-class-androidx-lifecycle-viewmodel-found-in-modules

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 を見に行きました。

追加したモジュールの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-viewmodelandroidx.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 モジュールを除外

前述の通りappcompatmaterialは自分の知識不足も相まって不信感が止まなかったのでその二つを除外してみることにしました。

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