Avatar ·

Ошибка "Duplicate class" в Kotlin/Android проекте: причины и исправление

Привет всем! Я новичок в разработке под Android на Kotlin, и столкнулся с проблемой, которая не дает мне собрать проект. После добавления нескольких библиотек в `build.gradle.kts` я получаю ошибку: ``` Duplicate class kotlin.collections.jdk8.CollectionsJDK8Kt found in modules kotlin-stdlib-1.8.0 (org.jetbrains.kotlin:kotlin-stdlib:1.8.0) and kotlin-stdlib-jdk8-1.7.0 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0) ``` Вот мой `build.gradle.kts` (app level): ```kotlin plugins { id("com.android.application") id("org.jetbrains.kotlin.android") version "1.8.0" } android { compileSdk = 34 defaultConfig { applicationId = "com.example.myapp" minSdk = 24 targetSdk = 34 versionCode = 1 versionName = "1.0" } } dependencies { implementation("androidx.core:core-ktx:1.12.0") implementation("androidx.appcompat:appcompat:1.6.1") implementation("com.google.android.material:material:1.11.0") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.8.0") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0") implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:converter-gson:2.9.0") } ``` Я понимаю, что ошибка говорит о дублировании класса из `kotlin-stdlib` и `kotlin-stdlib-jdk8`, но не понимаю, как это исправить. Я пробовал удалить одну из зависимостей, но тогда перестают работать другие библиотеки. Подскажите, пожалуйста, как правильно решить эту проблему? Может быть, я неправильно настраиваю версии Kotlin? Заранее спасибо! <<>>

Причина ошибки "Duplicate class"

Вы столкнулись с типичной проблемой конфликта версий Kotlin в Android проекте. Ошибка возникает, потому что:

  • kotlin-stdlib:1.8.0 — это стандартная библиотека Kotlin версии 1.8.0.
  • kotlin-stdlib-jdk8:1.7.0 — это расширение стандартной библиотеки для Java 8, но оно уже включено в состав kotlin-stdlib начиная с Kotlin 1.2.50.
  • Вы явно добавили обе зависимости с разными версиями (1.8.0 и 1.7.0), что приводит к дублированию классов.

Более того, сам плагин org.jetbrains.kotlin.android версии 1.8.0 уже автоматически добавляет kotlin-stdlib в ваш проект. Явное указание implementation("org.jetbrains.kotlin:kotlin-stdlib:1.8.0") может быть избыточным и также привести к дублированию.

Решение: правильная настройка зависимостей

Вам нужно удалить явные зависимости kotlin-stdlib и kotlin-stdlib-jdk8, так как они автоматически подтягиваются плагином. Исправленный build.gradle.kts (app level) будет выглядеть так:

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android") version "1.8.0"
}

android {
    compileSdk = 34
    defaultConfig {
        applicationId = "com.example.myapp"
        minSdk = 24
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"
    }
}

dependencies {
    implementation("androidx.core:core-ktx:1.12.0")
    implementation("androidx.appcompat:appcompat:1.6.1")
    implementation("com.google.android.material:material:1.11.0")
    // УДАЛЕНЫ: kotlin-stdlib и kotlin-stdlib-jdk8
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
    implementation("com.squareup.retrofit2:converter-gson:2.9.0")
}

Дополнительные рекомендации

  • Единая версия Kotlin: Убедитесь, что версия плагина Kotlin (org.jetbrains.kotlin.android) совпадает с версией, используемой другими библиотеками (например, KSP, kotlinx-coroutines). Для проверки выполните в терминале: ./gradlew dependencies --configuration debugRuntimeClasspath | grep kotlin.
  • Использование BOM (Bill of Materials): Если вы используете много библиотек Kotlin, рассмотрите подключение BOM для централизованного управления версиями. Например, для Kotlin Coroutines добавьте implementation(platform("org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.7.3")).
  • Конфликт транзитивных зависимостей: Если после удаления явных зависимостей ошибка осталась, это может быть вызвано транзитивными зависимостями. Используйте команду ./gradlew :app:dependencies для визуализации дерева зависимостей и поиска дублирующихся библиотек. Затем примените exclude или force в блоке configurations.all:
configurations.all {
    resolutionStrategy {
        force("org.jetbrains.kotlin:kotlin-stdlib:1.8.0")
        // Исключить устаревший модуль
        exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk8")
    }
}

Проверка результата

После внесения изменений выполните Clean Project (Build → Clean Project) и затем Rebuild Project. Ошибка "Duplicate class" должна исчезнуть. Если проблема сохраняется, проверьте, не используете ли вы плагин kotlin-android-extensions (устарел) или не подключены ли модули с разными версиями Kotlin в многомодульном проекте.

<<>>

Альтернативный подход: использование force с resolutionStrategy

Если по каким-то причинам вы не можете удалить зависимости (например, они требуются для других модулей), можно принудительно задать единую версию Kotlin для всех зависимостей. Это особенно полезно в многомодульных проектах, где разные модули могут тянуть разные версии.

Добавьте следующий блок в ваш build.gradle.kts (app level) внутри блока android или на уровне проекта:

configurations.all {
    resolutionStrategy {
        // Принудительно используем версию 1.8.0 для всех модулей kotlin-stdlib
        force("org.jetbrains.kotlin:kotlin-stdlib:1.8.0")
        force("org.jetbrains.kotlin:kotlin-stdlib-common:1.8.0")
        // Исключаем устаревшие модули
        exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk7")
        exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk8")
    }
}

Этот метод гарантирует, что все транзитивные зависимости будут использовать только указанную версию Kotlin. Однако помните: такой подход может скрыть реальные проблемы совместимости библиотек, поэтому используйте его как временное решение. В идеале, обновите все библиотеки до версий, совместимых с вашей версией Kotlin (1.8.0).

Также полезно добавить в gradle.properties строку kotlin.stdlib.default.dependency=false, чтобы предотвратить автоматическое добавление стандартной библиотеки плагином, если вы управляете ей вручную.