[Разработка под Android, Gradle] Отключаем Jetifier и ускоряем сборку: опыт Тинькофф.Бизнес

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
30-Дек-2020 17:31


Привет, Хабр!Уже пять лет наша команда разрабатывает Тинькофф.Бизнес – мобильный банк для юридических лиц и ИП. За это время наше 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. Получилось? Если нет – вы увидите примерно следующую ошибку:
Это связано с тем, что в classpath есть легаси android.support зависимость, и она конфликтует с ее androidx-аналогом. Для отключения Jetifier'а нужно сделать так, чтобы в графе зависимостей не было ни одной саппорт-библиотеки. Давайте посмотрим на полный список зависимостей в нашем проекте. Открываем терминал и запускаем следующую команду:./gradlew :app:dependencies --configuration=releaseRuntimeClasspath
Здесь можно видеть, что модуль app использует mosby-mvp, который тянет за собой support-библиотеки. В случае, если ваш проект довольно большой и имеет много зависимостей, :app:dependencies может быть не совсем удобным способом отлавливать легаси-зависимости, на этот случай можно использовать плагин Can I Drop Jetifier: он анализирует граф зависимостей проекта и смотрит, есть ли среди них те, что ссылаются на android.support библиотеки, агрегируя их в один список.Давайте применим плагин и вызовем ./gradlew -Pandroid.enableJetifier=false canIDropJetifier
Теперь вместо большого лога зависимостей мы можем видеть только те, что мешают нам выключить 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]}"
...
Далее после прогона мы получили следующие метрики:Время сборкиJetifiedNon-JetifiedMean23,5 sec28,5 secMin22 sec26 secMax25 sec31 secУ нас было не так много легаси-зависимостей, которые пришлось перевести на androidx руками, но тем не менее, прогнав на них Jetifier, нам удалось отнять целых 5 секунд из среднего времени сборки. При большом количестве зависимостей эта цифра будет только расти.Еще больше метрик и самых разных новостей о Тинькофф.Бизнес можно увидеть у нас в Телеграм-канале Tinkoffhere!
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_razrabotka_pod_android (Разработка под Android), #_gradle, #_jetifier, #_tinkoff, #_tinkoff.ru, #_gradle, #_performance, #_blog_kompanii_tinkoff (
Блог компании Tinkoff
)
, #_razrabotka_pod_android (
Разработка под Android
)
, #_gradle
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Ноя 14:37
Часовой пояс: UTC + 5