Подтвердить что ты не робот

Общий код для разных андроидов

Я создаю 4 разных вкуса своего приложения для Android.

У меня есть класс Customization.java, который одинаковый для 3 из них и отличается для 1.

Поскольку я не могу поместить тот же класс как в основную папку, так и в папку с ароматом, теперь я должен поддерживать 3 копии одного и того же класса для этих 3 вариантов.

Можно ли каким-либо образом сохранить только две версии этого класса?

Вещи, которые я рассмотрел до сих пор:

  • Я посмотрел на размеры вкуса, но оказывается, что в этом случае они неприменимы.
  • Сохранение всего одного файла в одном из вариантов и копирование его через мою сборку script.

Мне интересно, есть ли что-то более чистое из коробки.

4b9b3361

Ответ 1

Я хочу преобразовать комментарий CommonsWare к ответу. Затем я объясню, как должна выглядеть конечная настройка каталога. Надеюсь, это поможет людям наткнуться на этот вопрос через поиск.

Ну, вы можете переопределить ресурсы в ароматах. Итак, в main/res/layout/ и специфичный для вкуса в yourFlavorHere/res/layout/.

Итак, если файл компоновки Customization называется activity_customization.xml, вы оставите его общую копию, разделяемую между тремя вариантами в каталоге src/main/res/layout, и поместите модифицированный макет xml, который будет использоваться, скажем flavorFour, в соответствии с его исходным каталогом источника src/flavorFour/res/layout.

Как это работает, так как ароматы от одного до трех (в отличие от вкуса четыре) не предоставили свои собственные версии activity_customization.xml, они наследуют тот, который поступает из набора main.

Это класс активности Java, который становится сложным. Другая возможность для то есть настроить вкусы с одинаковой реализацией вытащить из двух исходных каталогов: специфичный для вкуса и общий с общей реализацией класса.

В отличие от ресурсов, файлы кода Java не объединяются и не переопределяются. Таким образом, у вас не может быть файлов Java с тем же полным именем класса под main, а также в любом из ваших наборов источников аромата. Если вы это сделаете, вы получите двойную ошибку класса.

Чтобы решить эту проблему, самым простым решением является перенос активности Customization из main и в каждый набор источников аромата. Это работает, потому что каталоги вкуса взаимоисключающие (друг с другом, а не с main), следовательно, избегают конфликта.

Но это означает, что у трех из четырех ароматов есть дублирующая копия активности - кошмар для обслуживания - только потому, что один из ароматов потребовал некоторых изменений. Чтобы решить эту проблему, мы можем ввести другой исходный каталог, в котором хранятся только общие файлы кодов, разделяемые между тремя вариантами.

Итак, build.gradle script будет выглядеть примерно так:

android {
    ...
    productFlavors {
        flavorOne {
            ...
        }
        flavorTwo {
            ...
        }
        flavorThree {
            ...
        }
        flavorFour {
            ...
        }
    }
    sourceSets {
        flavorOne.java.srcDir 'src/common/java'
        flavorTwo.java.srcDir 'src/common/java'
        flavorThree.java.srcDir 'src/common/java'
    }
}

Обратите внимание на использование java.srcDir (а не srcDirs), который добавляет другой исходный каталог Java в уже существующий по умолчанию src/flavorX/java.

Теперь все, что нам нужно сделать, это сбросить общий файл активности Customization в src/common/java, чтобы сделать его доступным для вкусов от одного до трех. Измененная версия, требуемая flavorFour, попадет под свой собственный исходный набор в src/flavorFour/java.

Итак, окончательная структура проекта будет выглядеть примерно как

+ App // module
|- src
   |- common // shared srcDir
      |- java
       |- path/to/pkg
         |- CustomizationActivity.java // inherited by flavors 1, 2, 3
   + flavorOne
   + flavorTwo
   + flavorThree
   + flavorFour
      |- java
       |- path/to/pkg
         |- CustomizationActivity.java // per-flavor activity class
      |- res
         |- layout
            |- activity_customization.xml // overrides src/main/res/layout
   |- main
      + java
      |- res
         |- layout
            |- activity_customization.xml // inherited by flavors 1, 2, 3

Ответ 2

Я использую это для переопределения кодов в течение 5 лет, просто добавьте фрагмент кода в свой build.gradle.

Для последнего подключаемого модуля Gradle (> = 3.4.0):

android {
    ......
    applicationVariants.configureEach { ApplicationVariant variant ->
        AndroidSourceSet flavorSourceSet = android.sourceSets.findByName(variant.productFlavors[0].name);
        if (flavorSourceSet != null) {
            String flavorPath = flavorSourceSet.java.srcDirs[0].path;
            variant.javaCompileProvider.configure { task ->
                task.exclude { FileTreeElement elem ->
                    !elem.isDirectory() && !elem.file.parent.startsWith(flavorPath) &&
                        new File(flavorPath, elem.path).exists();
            }
        }
    }
}

Для старых плагинов Gradle:

android {
    ......
    applicationVariants.all { ApplicationVariant variant ->
        AndroidSourceSet flavorSourceSet = android.sourceSets.findByName(variant.productFlavors[0].name);
        if (flavorSourceSet != null) {
            variant.javaCompiler.doFirst {
                String flavorPath = flavorSourceSet.java.srcDirs[0].path;
                variant.javaCompiler.exclude { FileTreeElement elem ->
                    !elem.isDirectory() && !elem.file.parent.startsWith(flavorPath) &&
                            new File(flavorPath, elem.path).exists();
                }
            }
        }
    }

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