![](https://habrastorage.org/getpro/habr/upload_files/f68/5ca/5d4/f685ca5d48af6f852d7a02b2854b4e59.png)
Привет, Хабр!
Уже пять лет наша команда разрабатывает Тинькофф.Бизнес – мобильный банк для юридических лиц и ИП. За это время наше android-приложение успело набрать целых 200 модулей и 400 тысяч строк компилируемого кода.
Модуляризация приложения не всегда идет ему на пользу. Нам приходится решать большое количество задач и проблем, связанных со скоростью сборки.
В этой статье я расскажу и покажу, как мы ускорили билд, отключив Jetifier.
Преамбула
Jetifier был представлен еще в далеком 2018 году вместе с AndroidX – классной заменой support
библиотекам, компоненты которой могут поддерживаться и обновляться независимо друг от друга.
Сам по себе Jetifier довольно сложен, но принцип его работы прост как три копейки: он проходится по всем библиотекам, которые есть у вас в проекте и заменяет в них android.support
зависимости на их androidx
аналог.
В результате мы получаем еще один шаг сборки, который может занять довольно много времени, а до появления AGP 4.1.0 еще и никак не кэшировал результат своего выполнения и замедлял даже инкрементальный билд.
Конечно же нам хотелось бы избавиться от него. Как?
Отключаем Jetifier
На самом деле все может быть довольно просто. Попробуйте зайти в gradle.properties
и проставить там заветный android.enableJetifier=false
, а затем выполнить Gradle sync и build. Получилось? Если нет – вы увидите примерно следующую ошибку:
![](https://habrastorage.org/getpro/habr/upload_files/339/0c8/fec/3390c8fec7c5763cf68c32a16755353b.png)
Это связано с тем, что в classpath есть легаси android.support
зависимость, и она конфликтует с ее androidx-аналогом. Для отключения Jetifier'а нужно сделать так, чтобы в графе зависимостей не было ни одной саппорт-библиотеки. Давайте посмотрим на полный список зависимостей в нашем проекте. Открываем терминал и запускаем следующую команду:
./gradlew :app:dependencies --configuration=releaseRuntimeClasspath
![](https://habrastorage.org/getpro/habr/upload_files/c3e/aff/287/c3eaff287986aff09ce7056b2a2778d5.png)
Здесь можно видеть, что модуль app
использует mosby-mvp
, который тянет за собой support
-библиотеки.
В случае, если ваш проект довольно большой и имеет много зависимостей, :app:dependencies
может быть не совсем удобным способом отлавливать легаси-зависимости, на этот случай можно использовать плагин Can I Drop Jetifier: он анализирует граф зависимостей проекта и смотрит, есть ли среди них те, что ссылаются на android.support
библиотеки, агрегируя их в один список.
Давайте применим плагин и вызовем ./gradlew -Pandroid.enableJetifier=false canIDropJetifier
![](https://habrastorage.org/getpro/habr/upload_files/1fd/135/295/1fd13529515a9f67ad1d6dd66b4d2aa3.png)
Теперь вместо большого лога зависимостей мы можем видеть только те, что мешают нам выключить Jetifier.
Отлично! Давайте теперь на примере mosby.mvp
рассмотрим способ миграции библиотеки на androidx
.
Для этого нам нужно выполнить несколько шагов:
Проверить версию библиотеки – если есть более новая, в которой нет
support
зависимостей – обновляемся. Если нет – переходим на следующий шаг.Найти библиотеку в репозиториях. Например,
mosby.mvp
лежит на mavenСкачиваем
.pom
и.aar
файлы.Открываем
.pom
файл и меняем<groupId>
– добавляем в него префиксjetified.
, чтобы ничего не перепутатьВручную заменяем все
android.support
зависимости на ихandroidx
аналог, воспользовавшись этими маппингами.Если зависимости содержат другие артефакты из этой группы, использующие
android.support
– с ними придется провести такую же процедуру.Скачиваем jetifier-standalone и прогоняем через него скачанный
.aar
файл с зависимостью../jetifier-standalone -i <source-library> -o <output-library>
Загружаем
.pom
и.aar
файлы в любой доступный вам менеджер репозиториев. У нас это Nexus, если же у вас его нет – можете просто положить .aar к себе в проект.
Легаси-зависимость может также тянуться через какой-нибудь core/common модуль в вашем проекте. В этом случае нам нужно "заставить" Gradle использовать именно jetified-версию зависимости.
Для этого в build.gradle нужно прописать примерно следующее:
configurations.all { configuration ->
resolutionStrategy {
dependencySubstitution {
substitute module("com.hannesdorfmann.mosby3:mvp:3.1.1") with module("jetified.com.hannesdorfmann.mosby3:mvp:3.1.1")
}
}
}
Готово! Выполнив эти шаги, мы получаем jetified-артефакт, который можем использовать у себя в проекте.
Давайте посмотрим, какой выигрыш мы от этого получили.
Метрики
Для сбора метрик отлично подойдет Gradle Profiler. Для его запуска мы написали простой .sh
скрипт и положили его в корневую папку проекта.
#!/bin/bash
echo "Cloning gradle-profiler repository..."
git clone https://github.com/gradle/gradle-profiler.git
cd gradle-profiler
./gradlew installDist
cd ..
./gradle-profiler/build/install/gradle-profiler/bin/gradle-profiler --benchmark --iterations 4 --warmups 3 --project-dir ./ :rko:assembleDebug
echo "searching for statistics..."
medians=$(grep "median" profile-out/benchmark.csv)
IFS=', ' read -r -a array <<< "$medians"
echo "configurationTime = ${array[1]}"
echo "syncTime = ${array[2]}"
...
Далее после прогона мы получили следующие метрики:
Время сборки | Jetified | Non-Jetified |
Mean | 23,5 sec | 28,5 sec |
Min | 22 sec | 26 sec |
Max | 25 sec | 31 sec |
У нас было не так много легаси-зависимостей, которые пришлось перевести на androidx
руками, но тем не менее, прогнав на них Jetifier, нам удалось отнять целых 5 секунд из среднего времени сборки. При большом количестве зависимостей эта цифра будет только расти.
Еще больше метрик и самых разных новостей о Тинькофф.Бизнес можно увидеть у нас в Телеграм-канале Tinkoffhere!