Avatar ·

Ошибка Program type already present: CoordinatorLayout$Behavior при сборке с Dagger 2

Всем привет! Я новичок в Kotlin и пытаюсь собрать проект с использованием Dagger 2. Проект использует Android Support Library, и я недавно добавил CoordinatorLayout для реализации BottomSheetBehavior. При сборке я получаю ошибку: ``` Error : Program type already present: android.support.design.widget.CoordinatorLayout$Behavior ``` Вот фрагмент моего `build.gradle` (Module: app): ```kotlin dependencies { implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support:design:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation 'com.google.dagger:dagger:2.21' kapt 'com.google.dagger:dagger-compiler:2.21' // другие зависимости... } ``` И в коде я использую: ```kotlin class MyBottomSheetBehavior(context: Context, attrs: AttributeSet?) : CoordinatorLayout.Behavior(context, attrs) { // кастомная логика } ``` Ошибка возникает на этапе компиляции, причём только после добавления Dagger 2. Без Dagger всё работает нормально. Я пробовал чистить кэш (Build > Clean Project), но это не помогает. Подскажите, в чём может быть проблема и как её исправить? <<>>

Причина проблемы: дублирование классов из Support Library

Ошибка Program type already present возникает, когда один и тот же класс загружается из разных JAR/AAR файлов. В вашем случае класс CoordinatorLayout$Behavior присутствует в двух местах:

  • В библиотеке com.android.support:design
  • В одной из транзитивных зависимостей Dagger 2 (или её компилятора)

Проблема в том, что Dagger 2 (версия 2.21) тянет за собой старую версию Support Library через свою внутреннюю зависимость com.google.dagger:dagger-producers. Эта старая версия содержит те же классы, что и ваша com.android.support:design, но из другого пакета. В результате Gradle не может разрешить конфликт.

Решение: принудительное указание версий через resolutionStrategy

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

android {
    // ... ваши настройки
    
    configurations.all {
        resolutionStrategy.eachDependency { details ->
            if (details.requested.group == 'com.android.support') {
                details.useVersion '28.0.0'
            }
        }
    }
}

Это заставит Gradle использовать версию 28.0.0 для ВСЕХ зависимостей из группы com.android.support, включая те, что тянутся транзитивно через Dagger.

Альтернативное решение: обновление Dagger до последней версии

В более новых версиях Dagger (начиная с 2.27) эта проблема исправлена. Обновите зависимости:

implementation 'com.google.dagger:dagger:2.48'
kapt 'com.google.dagger:dagger-compiler:2.48'
// Если используете Android-инъекции:
implementation 'com.google.dagger:dagger-android:2.48'
implementation 'com.google.dagger:dagger-android-support:2.48'
kapt 'com.google.dagger:dagger-android-processor:2.48'

Полный пример исправленного build.gradle

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 28
    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 28
    }
    
    configurations.all {
        resolutionStrategy.eachDependency { details ->
            if (details.requested.group == 'com.android.support') {
                details.useVersion '28.0.0'
            }
        }
    }
}

dependencies {
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support:design:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    
    implementation 'com.google.dagger:dagger:2.48'
    kapt 'com.google.dagger:dagger-compiler:2.48'
    // Android-injection (опционально)
    implementation 'com.google.dagger:dagger-android:2.48'
    implementation 'com.google.dagger:dagger-android-support:2.48'
    kapt 'com.google.dagger:dagger-android-processor:2.48'
}

После добавления resolutionStrategy выполните File > Sync Project with Gradle Files и Build > Clean Project. Ошибка должна исчезнуть.

<<>>

Дополнительный подход: миграция на AndroidX

Если ваш проект позволяет, рекомендую полностью перейти на AndroidX. Это современный стандарт, который устраняет конфликты между старыми Support Library и новыми библиотеками. Для этого:

  1. В gradle.properties добавьте:
    android.useAndroidX=true
    android.enableJetifier=true
  2. Замените все импорты android.support.* на androidx.*:
    // Было:
    import android.support.design.widget.CoordinatorLayout
    
    // Стало:
    import androidx.coordinatorlayout.widget.CoordinatorLayout
  3. Обновите зависимости в build.gradle:
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.11.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

После миграции на AndroidX Dagger 2 (даже старые версии) перестаёт конфликтовать, так как библиотеки AndroidX не пересекаются по именам классов с Support Library. Это более чистое и долгосрочное решение, которое также упростит добавление новых зависимостей в будущем.