Проблема:
Я предполагаю, что моя проблема довольно распространена. У меня довольно большая база кода gradle, из которой я создаю настраиваемые версии с использованием вкусов продукта. Этим товарам часто требуется индивидуальная версия одного или нескольких классов из src\main\java
.
Я прочитал документацию gradle и также столкнулся со следующими вопросами, рассматривая ту же проблему:
Использование Build Flavors - структурирование исходных папок и правильное создание .gradle
Создавайте ароматы для разных версий того же класса
Я понимаю, почему вы не можете определить тот же класс в src\main\java
, а также в ваших вкусах, однако решение о перемещении класса из src\main\java
в ваш вкус продукта имеет довольно серьезный недостаток. Когда вы перемещаете класс из src\main\java
в свой последний вкус, чтобы настроить его, вам также нужно переместить копию оригинальной нестандартной версии этого класса в любой другой предыдущий продукт, или они больше не будут построены.
Вам может потребоваться только один раз выбрать один или два разных класса из оригиналов (а затем перефразировать эти классы в каталогах вкусов), но со временем количество перемещенных классов будет построено, а число, оставшееся в src\main\java
будет уменьшаться каждый раз, когда вы это сделаете. В конце концов большинство классов будут в ароматах (хотя большинство будет копиями оригиналов), а src\main\java
будет почти пустым, что приведет к победе цели всей структуры сборки gradle.
Кроме того, вам нужно будет сохранить "стандартный" вкус, который вы можете клонировать каждый раз, когда вы начинаете новый вкус, поэтому вы знаете, что начинаете со всех классов в соответствии с исходной базой кода.
Мое начальное решение:
Использовать поля в BuildConfig для определения использования пользовательского класса или нет:
buildConfigField 'boolean', 'CUSTOM_ACTIVITY_X', 'true'
Затем вы можете использовать код, например:
final Intent intent = new Intent();
...
if (BuildConfig.CUSTOM_ACTIVITY_X) {
intent.setClass(ThisActivity.this, CustomActivityX.class);
} else {
intent.setClass(ThisActivity.this, DefaultActivityX.class);
}
startActivity(intent);
Каждому аромату все равно понадобится копия CustomActivityX, но она может быть просто пустым пустым классом в ароматах, где вы знаете, что он не будет использоваться. Это означает, что ваши версии по умолчанию для классов всегда сохраняются в src\main\java
.
Улучшенный обходной путь:
При попытке избавиться от необходимости создания фиктивного CustomActivityX в каждом другом вкусе, я посмотрел на использование Class.forName()
.
Например:
final Class activityX;
if (BuildConfig.CUSTOM_ACTIVITY_X) {
try {
activityX = Class.forName("CustomActivityX");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} else {
activityX = DefaultActivityX.class;
}
final Intent intent = new Intent();
...
intent.setClass(ThisActivity.this, activityX);
startActivity(intent);
Однако это, очевидно, приводит к тому, что "activityX может не быть инициализировано" при попытке использовать его из-за блока try/catch
.
Как это можно преодолеть?