← Назад к вопросам

Что такое SourceSets?

1.0 Junior🔥 152 комментариев
#Многомодульность

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое SourceSets в контексте Android-разработки?

SourceSets (исходные наборы) — это центральная концепция системы сборки Gradle, используемая для организации исходного кода, ресурсов и конфигурационных файлов в Android-проекте. По сути, это абстракция, которая группирует логически связанные файлы и определяет, куда сборщик будет смотреть в процессе компиляции приложения. В Android Studio эта структура отражена в стандартных папках main, test и androidTest.

Основное назначение и компоненты SourceSet

Каждый SourceSet включает три ключевых типа директорий:

  1. Java/Kotlin исходный код: Файлы .java, .kt.
  2. Ресурсы (Resources): Макеты (layout), строки (values), изображения (drawable), меню, XML-конфигурации и т.д.
  3. Android-манифесты: Файлы AndroidManifest.xml.

Базовый набор SourceSet'ов в модуле включает:

  • main: Основной набор для production-кода приложения. Обязателен.
  • test: Набор для unit-тестов, которые выполняются на JVM без эмулятора/устройства.
  • androidTest: Набор для инструментальных тестов (UI-тесты, интеграционные), требующих запуска на Android-устройстве или эмуляторе.

Конфигурация и использование в build.gradle

По умолчанию Gradle ожидает стандартную иерархию папок. Однако логику можно гибко настраивать в файле модуля build.gradle.kts (Kotlin DSL):

android {
    sourceSets {
        getByName("main") {
            // Переназначение путей для main sourceSet
            manifest.srcFile("src/main/AndroidManifest.xml")
            java.srcDirs("src/main/kotlin", "src/shared/kotlin")
            res.srcDirs("src/main/res", "src/shared/res")
            assets.srcDirs("src/main/assets")
        }

        getByName("debug") {
            // Конфигурация для buildType "debug"
            java.srcDirs("src/debug/kotlin")
            res.srcDirs("src/debug/res")
            // Можно указать отдельный манифест для отладки
            manifest.srcFile("src/debug/AndroidManifest.xml")
        }

        create("demo") {
            // Создание кастомного sourceSet для productFlavor "demo"
            java.srcDirs("src/demo/kotlin")
            res.srcDirs("src/demo/res")
            // Наследует всё из 'main', но файлы здесь имеют приоритет
        }
    }
}

Механизм слияния (Merge) и приоритеты

Слияние — критически важный аспект работы SourceSets. Когда сборщик создаёт APK, он объединяет файлы из всех активных наборов. Приоритет при конфликтах (одинаковые имена файлов) следующий (от низшего к высшему):

Build Type (e.g., debug) > Product Flavor (e.g., demo) > main

Например, если main/res/values/strings.xml и debug/res/values/strings.xml содержат строку с одинаковым ключом app_name, будет использована версия из debug.

Практические сценарии использования

  1. Разделение конфигураций для разных сборок: Для debug и release можно использовать разные:
    *   **Манифесты:** Добавлять `INTERNET` permission только в `debug`.
    *   **Ресурсы:** Менять иконку или тексты для отладочной версии.
    *   **Код:** Реализовать логгер, показывающий только в `debug`.

  1. Создание productFlavors (вариаций продукта): Разные версии приложения (бесплатная/платная, для разных брендов) имеют свои собственные java, res, manifest в отдельных SourceSets (например, free и paid).

  2. Выделение общего кода: Можно создать кастомный SourceSet (например, shared), который будет использоваться несколькими модулями или flavor, чтобы избежать дублирования.

// Пример: подключение общей папки с кодом к нескольким flavor
android {
    productFlavors {
        create("free") {
            // ...
        }
        create("paid") {
            // ...
        }
    }

    sourceSets {
        getByName("free").java.srcDirs("src/sharedFree/kotlin")
        getByName("paid").java.srcDirs("src/sharedPaid/kotlin")
        // Оба flavor наследуют код из src/shared/kotlin через main
    }
}

Важные особенности

  • Наследование: Каждый SourceSet автоматически включает в себя содержимое main. Файлы с одинаковыми именами в производных наборах переопределяют файлы из main.
  • Структура директорий: Именование папок по шаблону src/<sourceSetName> (src/main, src/debug, src/freeDebug) — это соглашение, а не абсолютное требование. Пути можно переназначать, как показано выше.
  • Производительность: Правильное использование SourceSets улучшает структуру проекта и может ускорить инкрементальные сборки, так как Gradle перекомпилирует только изменённые наборы.

Итог: SourceSets — это мощный механизм для управления сложностью многомодульных проектов и создания различных конфигураций одного приложения. Понимание их работы позволяет разработчику эффективно организовывать код, тесты и ресурсы для разных типов сборок, сред и вариантов продукта, соблюдая принцип DRY и обеспечивая чистую архитектуру проекта.