Duplicate class в Kotlin Android: Топ-5 ошибок и решения

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: «Двойник» в вашем проекте

Представьте ситуацию: вы пишете код на Kotlin для Android, всё работает отлично. Вы добавляете новую библиотеку, запускаете сборку — и Gradle выдает красную ошибку: «Duplicate class». Знакомо? Если вы хоть раз сталкивались с Android-разработкой, то наверняка видели это сообщение. На Stack Overflow этот вопрос набрал тысячи просмотров, и не зря — ошибка может вывести из себя даже опытного разработчика.

В этой статье мы разберем, что такое Duplicate class в Kotlin Android, почему она возникает, и главное — как её исправить раз и навсегда. Вы узнаете 5 самых частых причин, получите готовые решения и научитесь предотвращать конфликты зависимостей. Поехали!

Что такое Duplicate class и почему это происходит?

Ошибка Duplicate class возникает, когда система сборки (Gradle) находит два или более одинаковых класса с одним полным именем (FQN — Fully Qualified Name). В мире Android это обычно означает, что один и тот же класс присутствует в разных библиотеках или модулях вашего проекта.

Представьте, что вы заказали две одинаковые книги, но от разных издателей. Они лежат на одной полке — и библиотекарь не знает, какую брать. Так и Gradle: он не может решить, какой из дублирующихся классов использовать.

Почему это особенно актуально для Kotlin? Kotlin активно использует стандартную библиотеку Kotlin (kotlin-stdlib), которая может конфликтовать с её же версиями из других источников. Добавьте сюда AndroidX, библиотеки Google, Firebase — и вы получите гремучую смесь.

Топ-5 причин ошибки Duplicate class в Kotlin Android

Мы собрали самые частые сценарии, с которыми вы столкнетесь в реальной разработке. Каждый пункт сопровождается примером кода и решением.

1. Конфликт версий Kotlin stdlib

Это король всех дубликатов. Когда вы подключаете библиотеку, которая тянет свою версию kotlin-stdlib, а у вас в проекте уже есть другая — возникает конфликт.

Пример:

// build.gradle.kts (модуль app)
dependencies {
    implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.0")
    implementation("com.some.library:example:2.0.0") // эта библиотека тянет kotlin-stdlib:1.8.0
}

Gradle выдаст что-то вроде:

Duplicate class kotlin.collections.ArraysKt found in modules kotlin-stdlib-1.9.0 (org.jetbrains.kotlin:kotlin-stdlib:1.9.0) and kotlin-stdlib-1.8.0 (org.jetbrains.kotlin:kotlin-stdlib:1.8.0)

Решение: Используйте единую версию Kotlin для всего проекта. Лучший способ — задать её в корневом build.gradle.kts:

// build.gradle.kts (корневой)
plugins {
    kotlin("android") version "1.9.0" apply false
}

// build.gradle.kts (модуль app)
plugins {
    kotlin("android")
}

Также можно явно исключить зависимость:

implementation("com.some.library:example:2.0.0") {
    exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib")
}

2. Дублирование AndroidX и Support Library

Классика жанра. Если вы используете старые библиотеки Support Library вместе с AndroidX, они содержат одинаковые классы (например, android.support.v4.app.Fragment и androidx.fragment.app.Fragment).

Пример ошибки:

Duplicate class android.support.v4.app.Fragment found in modules support-compat-28.0.0 and fragment-1.6.0

Решение:

  • Включите флаг android.useAndroidX=true в gradle.properties.
  • Убедитесь, что все библиотеки переведены на AndroidX. Используйте инструмент миграции в Android Studio (Refactor > Migrate to AndroidX).
  • Если библиотека не поддерживает AndroidX, используйте jetifier:
// gradle.properties
android.useAndroidX=true
android.enableJetifier=true

3. Конфликт из-за разных версий одной библиотеки

Вы подключаете две библиотеки, которые зависят от одного и того же пакета, но разных версий. Например, com.google.android.gms:play-services-maps и com.google.android.gms:play-services-location могут тянуть разные версии play-services-basement.

Пример:

dependencies {
    implementation("com.google.android.gms:play-services-maps:18.1.0")
    implementation("com.google.android.gms:play-services-location:21.0.1")
    // play-services-basement может дублироваться
}

Решение: Принудительно укажите единую версию через force или централизованное управление зависимостями:

// build.gradle.kts
configurations.all {
    resolutionStrategy {
        force("com.google.android.gms:play-services-basement:18.2.0")
    }
}

Или используйте Version Catalog (рекомендуется для больших проектов).

4. Одинаковые классы в разных модулях

Если у вас мультимодульный проект, и два модуля содержат класс с одним и тем же пакетом и именем — Gradle закричит. Это часто случается, когда вы копируете код или используете автосгенерированные файлы.

Пример:

// Модуль :feature:auth
package com.example.data
class UserRepository

// Модуль :feature:profile
package com.example.data
class UserRepository // Дубликат!

Решение:

  • Переименуйте классы или используйте разные пакеты.
  • Проверьте, не подключаете ли вы один модуль дважды (например, через implementation project и api project).
  • Используйте R8/ProGuard для обфускации, но это не решит проблему на этапе компиляции.

5. Библиотеки, которые включают один и тот же сторонний код

Некоторые библиотеки «запекают» внутрь себя другие библиотеки (fat JAR/AAR). Например, библиотека для работы с сетью может включать OkHttp, а другая — тоже. Если версии разные — получите Duplicate class.

Пример:

dependencies {
    implementation("com.example:network-lib:1.0.0") // содержит okhttp:3.12.0
    implementation("com.squareup.okhttp3:okhttp:4.10.0") // явно подключен
}

Решение: Используйте ./gradlew :app:dependencies для просмотра дерева зависимостей. Затем исключите дублиру

Блоги

Рекомендаций по книгам