Instant Run: як це працює?

Всім привіт! Дана стаття є перекладом нотатки Android-розробника і автора книги «Android 4. Програмування додатків для планшетних комп'ютерів і смартфонів» Рето Майєра. Над перекладом працював Android-відділ компанії Лайв Тайпинг. Оригінальна стаття доступна здесь.
Більшість людей цілком задоволені, коли їм в руки потрапляє щось просте і корисне. Але ми, програмісти, не ставимося до цієї більшості.
Взяти, приміром, Instant Run. Це фіча Android Studio, яка за допомогою «магії» скорочує час, що витрачається на складання і деплой инкриментальных змін коду в процесі написання / тестування / дебаггінга.
Я називаю це магією тому, що з боку все виглядає саме так. Після першого натискання Run або Debug все працює так, як того і слід очікувати. Проте кожного разу, коли в код вносяться зміни і знову натискається кнопка Run або Debug (але в цей раз — з іконкою у вигляді блискавки), зміни деплоятся на мій телефон настільки швидко, що я не встигаю це помітити.
Але давайте залишимо магію для недільних посиденьок біля телевізора.
Особисто мене більше влаштовує, коли магія приходить до мене в комплекті з драконами, політичними інтригами і несподіваними поворотами сюжету. Тому я зустрівся з командою інженерів, які працювали над Android Studio, щоб з'ясувати, як же Instant Run працює насправді.
Почнемо з цієї простої блок-схеми типового циклу складання програми.

Збірка, деплой/установка, запуск програми, запуск актівіті.
Цілі, які переслідує Instant Run, гранично прості: прибрати максимально можливу кількість цих кроків і максимально прискорити ті, які залишаться в результаті.
На практиці це означає:
· складання та деплой тільки инкриментальных змін;
· не перевстановлювати програму;
· не перезапускати програму;
· не перезапускати актівіті.
Гаряча, тепла і холодна заміни

Instant Run = збірка инткриментальных змін + гаряча, тепла чи холодна заміна.
Гаряча заміна: зміни вносяться у додаток без необхідності перезапуску і навіть без необхідності перезапуску поточної актівіті. Може бути використане для більшості найпростіших правок всередині реалізації методів.
Тепла заміна: для того, щоб поправки набули чинності, необхідно перезапустити актівіті. Зазвичай вимагається при зміні ресурсів.
Холодна заміна: перезапуск програми без необхідності перевстановлення). Вимагається при внесенні структурних змін, таких, як успадкування або зміна сигнатури методів.
Коли ви натискаєте Run або Debug, відбувається щось на зразок цього:

Маніфести збираються в один файл, який разом з ресурсами .dex-файлами упаковуються в АПК.
Ваші маніфести збираються і упаковуються разом з ресурсами в АПК. Точно так само ваші .java-файли компілюються у байткод, конвертуються в .dex-файли і відправляються у той же АПК.
У перший раз, коли ви натискаєте Run або Debug з включеним Instant Run, Gradle виконує кілька додаткових тасков.

Java Bytecode Instrumentation і App Server впроваджені в ваш debug APK-файл.
Bytecode Instrumentation додається в ваші .class-файли і новий App Server клас заинжекчен в ваш додаток.
Крім цього, додається нове визначення класу Application, яке впроваджує кастомні завантажувачі класів і запускає App Server. Для того, щоб ваш додаток змогла використати ці зміни, змінюється файл Android-маніфесту. Якщо ви створювали свій власний клас Application, Instant Run замінить його.
Тепер Instant Run запущений і відстежує всі зміни, які ви вносите в код. Так що наступного разу, коли ви натиснете Run або Debug, Instant Run постарається максимально скоротити процес складання, використовуючи гарячу, теплу або холодну заміну.
Перед тим, як застосувати зміни, Android Studio перевіряє наявність відкритого сокета в App Server, занедбаному всередині програми з включеним Instant Run. Він підтверджує, що додаток запущено, а його buildID, яке очікує Android Studio.
Гаряча заміна

Android Studio відстежує зміни у файлах в процесі розробки і запускає спеціальний Gradle-таск, щоб згенерувати .dex-файли тільки для змінених класів. Потім Android Studio підхоплює ці файли і деплоит їх в App Server, що працює всередині додатка.
Оскільки оригінальні версії наших класів вже існують в запущеному додатку, Gradle за допомогою Transformation API підміняє їх на нові. Після цього змінені класи підвантажуються App server'ом, використовуючи кастомні завантажувачі класів.

З цього моменту при кожному виклику методу всередині нашого додатка спеціальні інструменти, вбудовані в наші початкові класи, взаємодіють з App server'ом, щоб дізнатися, чи були вони оновлені.
Якщо це так, виконання делегується новим подмененным класів замість старого методу запускається його нова версія.

Якщо ви встановите точки налагодження, то в стектрейсе побачите виклики методу класу з ім'ям «override».
Перенаправлення методів добре спрацьовує в разі зміни реалізації самих методів, але що робити з тими речами, які завантажуються під час запуску актівіті?
Тепла заміна
Тепла заміна перезапускає актівіті. Ресурси завантажуються до запуску актівіті. Тому будь-яка модифікація вимагає перезавантаження актівіті для примусового перезавантаження ресурсів.
зараз зміна будь-якого ресурсу призводить до того, що всі ресурси перепаковываются і відправляються в вашу програму. Але ми посилено працюємо над пакувальником, який буде упаковувати і деплоить тільки нові або змінені ресурси.
Зверніть увагу:, що тепла заміна не буде працювати для ресурсів, згаданих в Android-маніфесті, а також у випадку змін, внесених у сам маніфест, оскільки значення цього файлу читаються в процесі інсталяції АПК. Зміни, що зачіпають маніфест, призведуть до повного циклу збірки і установки програми.
На жаль, перезапуск актівіті не зможе чарівним чином застосувати структурні зміни. Додавання, видалення або зміна анотацій, полів, сигнатур методів, зміна батьківських класів або статичних инициализаций вимагають холодної заміни.
Холодна заміна
Після деплоинга ваш додаток і його підпроекти розділені на декілька .dex-файлів. Класи розподілені по цих файлів в залежності від назв пакетів, в яких вони знаходяться. При холодній заміні .dex-файл, якому належить змінений клас, повністю перекомпилируется разом з іншими класами, що входять в нього, і заново деплоится.
Цей підхід спирається на здатність Android Runtime завантажувати декілька .dex-файлів (фіча, що з'явилася в ART) і тому може бути використаний тільки для пристроїв, що працюють на Android версії 5.0 (API Level 21) і вище.
На пристроях, що працюють на API Level 20 або нижче, а отже, використовують DALVIK, Android Studio деплоит APK цілком.
Хоча Instant Run дуже розумний, але повернути час назад він не в силах. Зміни в коді, які могли б бути застосовані шляхом гарячої заміни, але які впливають на ініціалізацію, запускається при першому старті програми, зажадають від вас перезапуску всього додатка, щоб вступити в силу.

Щоб виконати инкриментальную складання і перезапустити програму, натисніть Rerun (CTRL-CMD-r).
Поради та секрети
Instant Run контролюється Android Studio, тому запускайте/перезавантажуйте вашу debug-версію допомогою IDE — не робіть цього безпосередньо з пристрою, інакше вся ваша праця полетить коту під хвіст.
Більше детальний список рад доступний в Android-документації, але тут наведені основні моменти, які потрібно завжди тримати в пам'яті.
  1. Намагайтеся виділити максимум ресурсів для Gradle. Якщо ви виділите як мінімум 2 Гб пам'яті для Gradle Daemon JVM через jvmargs у файлі gradle.properties, то буде включений dex-in-process, що значно прискорить швидкість всіх збірок — Instant Run, так і простих. Ви можете самі поекспериментувати зі значеннями параметрів і їх ефект на час збірки, щоб знайти оптимальний варіант.
  2. Можливості, які надає ART, дозволяють вам вичавити максимум з Instant Run, якщо ви надасте minSdkVersion значення 21 або вище. Ви можете створити новий product flavor спеціально для дебаггінга і встановити значення minSdk=21.
    3.Не забувайте, що внесення змін до маніфест запустить повний цикл збірки і установки. Тому, якщо ваш процес складання автоматично оновлює будь-яку частину маніфесту (наприклад, змінює versionCode або versionName), вам потрібно відключити цю опцію в debug build variants.
  3. Instant Run працює тільки з основним процесом. Тому, якщо ваш додаток використовує кілька процесів, у всіх процесах крім основного замість гарячої і теплої заміни буде застосована холодна (або повна пересборка, якщо ваш API Level менше 21).
  4. Якщо ви працюєте в Windows, Windows Defender може стати причиною повільної роботи Instant Run. Ви можете уникнути цього, додавши папку з вашим проектом в список виключень Windows Defender.
  5. На момент написання статті Instant Run не підтримував Jack Compiler, інструментальні тести і деплоинг одночасно на кілька пристроїв.
Instant Run постійно розвивається, команда розробників досліджує нові техніки для збільшення кількості кейсів, що дозволяють застосовувати гарячу заміну і зменшення необхідність холодних замін або повної перезбирання.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.