Исследование технологии горячего обновления Flutter | Техническая команда JD Cloud

1. Предыстория спроса:

После того, как приложение будет выпущено на рынок, серьезные ошибки неизбежно будут препятствовать его использованию пользователями, поэтому необходимо использовать технологию горячего обновления для немедленного исправления ошибок без выпуска новой версии приложения. Требования к горячему обновлению для нативных приложений (например, Android и IOS) относительно зрелые, но в стеке технологий Flutter в настоящее время отсутствуют аналогичные технические решения, поэтому команде Flutter R&D также нужны аналогичные технологии горячего обновления.

2. Анализ направления технологии горячего обновления Flutter:

После анализа может быть три возможных решения: 1) Аналог среды RN 2) Структура динамического компонента страницы 3) Решение для настройки виртуальной машины Dart

Название программы принцип преимущество недостаток решение с открытым исходным кодом
RN-подобная схема Используйте JS для написания dart в синтаксисе Flutter, затем используйте JavaScript для преобразования XML DSL в атомарные компоненты виджета Flutter, а затем позвольте Flutter отображать Так как система ios имеет встроенную поддержку js, обновления могут быть реализованы на ios 1) Из-за кросс-языкового выполнения это влияет на производительность; стоимость обучения высока 2) На стороне Android необходимо ввести дополнительные библиотеки JS MXFlutter на мобильном QQ, выставка на 58.com
Схема динамического компонента страницы Вставьте/предварительно встройте DynamicWidget в код во время компиляции, затем динамически доставьте данные Json, сопоставьте согласованную семантику с данными в JSON и динамически замените содержимое виджета для реализации обновления. Может поддерживать обновления на обоих концах Android/iOS 1) обновление пользовательского интерфейса относительно просто, но динамическая бизнес-логика вызывает затруднения; 2) затраты на разработку семантического парсера относительно высоки, и его непросто поддерживать; 3) полный набор внешних и внутренних сервисов и инструментов. необходимый Tangram от Tmall, DinamicX от Taobao и т. д.
Решение для настройки виртуальной машины Dart Анализируя принцип виртуальной машины Dart, измените код Java/C++ уровня Flutter Engine для достижения цели горячего обновления; Небольшое влияние на производительность, высокая динамика, технически может заменить все страницы Flutter (включая пользовательский интерфейс, логику, файлы ресурсов). Поскольку используется собственный движок, необходимо поддерживать разные версии кода движка Flutter; Не с открытым исходным кодом

Поскольку другие методы имеют примеры с открытым исходным кодом, в этом случае основное внимание будет уделено третьему «решению для настройки виртуальной машины Dart» в качестве цели, а также исследованию и объяснению решения.

Три, предварительные знания

Прежде чем приступить к пониманию технического решения, необходимо заранее разобраться с некоторыми соответствующими техническими понятиями:

3.1 Режим компиляции флаттера

Языком разработки Flutter является Dart, и его режим компиляции исходит из режима компиляции Dart, в основном включая JIT (Just In Time) и AOT (Ahead Of Time).

имя режима компиляции функции преимущество недостаток
JIT Компиляция точно в срок, типичный пример V8, он может компилировать и запускать JS в режиме реального времени, нужно только ввести строку исходного кода, вы можете скомпилировать и запустить код Он может динамически доставлять и выполнять код, независимо от архитектуры ЦП, и может предоставлять динамический контент. 1. Большое количество строковых кодов заставляет JIT-компилятор тратить время и память 2. Производительность плохая;
АОТ Предварительно скомпилированный, типичный пример C/C++, скомпилированный в двоичный код с помощью GCC, а затем может быть загружен и выполнен после получения разрешения на установку. Предварительно скомпилированный, быстрая загрузка и выполнение 1. Архитектура ЦП отличается при компиляции 2. Сгенерированный пакет двоичного кода относительно большой 3. Двоичный код должен получить разрешение перед его выполнением и не может динамически обновляться в системе ios

Режимы компиляции Flutter: Debug, Release, Profile;

Режим компиляции флаттера функции
Отлаживать Соответствует режиму JIT, поддерживает устройства и симуляторы, включает утверждения, поддерживает быструю разработку и поддерживает HotReload, не оптимизирует размер пакета и скорость выполнения.
Выпускать Соответствует режиму AOT, поддерживает реальные устройства, не поддерживает эмуляторы, отключает всю информацию об отладке утверждений, оптимизирует размер пакета, скорость запуска и выполнения.
Профиль Подобно режиму выпуска, в нем сохраняются некоторые функции отладки, помогающие в анализе производительности;

3.2 Анализ продукта компиляции Flutter

Проект iOS/Android под Flutter, по сути, является стандартным проектом iOS/Android; платформа IOS: Flutter генерирует и встраивает App.framework и Flutter.framework в ios, добавляя оболочку (xcode_backend.sh) в BuildPhase; платформа Android: Flutter добавляет флаттер. jar и скомпилированные бинарные файлы на Android через gradle;

3.2.1 Анализ структуры уровня двигателя:

3.2.2 Анализ продуктов, скомпилированных под Android

3.2.3 Анализ продуктов компиляции IOS

4. Анализ технологических решений горячего обновления

4.1 Анализ бизнес-кода

В соответствии с анализом «3.3.1» ~ «3.3.2» можно определить, что бизнес-коды приложений IOS и Android состоят из четырех сегментов: kDartVmSnapshotData, kDartVmSnapshotInstructions, kDartIsolateSnapshotData, kDartIsolateSnapshotInstructions; теоретически, если загруженный сегмент кода может быть динамически заменен кодом сегмента данных для достижения цели.

имя примечание эффект примечание
kDartIsolateSnapshotData Изолировать сегмент данных Dart Информация о классе, глобальные переменные, указатели функций и т. д. Разрешить динамическую доставку
kDartIsolateSnapshotInstructions Раздел директивы Dart изолировать Содержит код AOT, выполняемый изолятом Dart. IOS не разрешает динамическую доставку
kDartVmSnapshotData vm изолировать сегмент данных Начальное состояние кучи Dart, разделяемое между изолятами Разрешить динамическую доставку
kDartVmSnapshotИнструкции vm изолировать сегмент инструкции Содержит инструкции AOT для общих программ, совместно используемых всеми изолятами Dart в виртуальной машине. IOS не разрешает динамическую доставку

Примечание. Значение isolate, snapshot, vm isolate объясняется следующим образом:

имя значение
изолировать Dart — это один поток, а isolate похож на поток, который можно понимать как поток в Dart. Разница между изолятом и потоком: память разделяется между потоками, но память не делится между изолятом и изолятом. Нет проблемы конкуренции замков. Два изолята являются полностью независимыми линиями выполнения, и каждый изолят имеет свой собственный цикл обработки событий. Они могут взаимодействовать друг с другом только путем отправки сообщений, поэтому его накладные расходы на ресурсы ниже, чем у потоков.
снимок Информация о классе, глобальные переменные и функциональные инструкции хранятся непосредственно на диске в сериализованном виде, который называется Snapshot (моментальный снимок).
ВМ изолировать В одном и том же процессе может быть много изолятов, но области кучи двух изолятов не могут использоваться совместно, поэтому для взаимодействия между несколькими изолятами используется официальный дизайн изолята ВМ, то есть kDartVmSnapshot.

4.2 Анализ загрузки бизнес-кода (время выполнения)

Согласно идее анализа 4.1, нам сначала нужно понять весь процесс загрузки кода при запуске Flutter, и процесс анализа выглядит следующим образом:

1) Процесс загрузки бизнес-кода Android-приложения:

2) Процесс загрузки бизнес-кода IOS-APP:

4.3 Составление и генерация бизнес-кода (при компиляции)

Согласно приведенному выше анализу, мы знаем структуру данных бизнес-кода Flutter и то, как его загружать во время выполнения, поэтому нам нужно только внести изменения во время компиляции, чтобы сгенерировать нужный нам сегмент кода и файл сегмента данных. Это достигается путем загрузки собственных артефактов сборки во время выполнения.

1) Вот подробный разбор процесса сборки собственного бизнес-кода с IOS:

** Существует завершенный процесс построения, который можно проанализировать.Основной процесс — «Код Dart (бизнес-код)» -> (через компилятор Dart gen_snapshot.cc) для создания файла сборки snapshot_assemble.S -> (через xcrun) для создания obj-файла snapshot_assemble.o -> создается App.Framework (через цепочку инструментов xcun clang).

2) Процесс сборки продукта для Android аналогичен IOS. Поскольку у Android есть другие более простые решения, подробный анализ процесса сборки опущен, примерно следующим образом:

4.4 Поиск решений для реализации горячего обновления

По приведенным выше результатам технического анализа вы уже можете самостоятельно генерировать собственные файлы сегментов кода и сегментов данных. Изменяя базовый код виртуальной машины, ее также можно динамически загружать и запускать. Однако, поскольку текущая базовая система системы IOS не может динамически загружать данные о сегментах кода, доступные для чтения и записи, в память, все еще существуют технические трудности, которые необходимо преодолеть. Однако на стороне Android есть более простой путь решения, поэтому в следующем примере используется сторона Android, чтобы сосредоточиться на анализе идей, примерно как показано на следующем рисунке:

Как видно из рисунка выше, основные этапы горячего восстановления на стороне Android следующие:

1. Измените код Flutter Engine для загрузки libapp.so и flutter_aasets по указанному пути, например, в приватный каталог (data/data/files);

2. При компиляции APK используйте плагин Gradle Transform для динамической замены официального движка Flutter в соответствии с версией движка Flutter SDK и, наконец, запишите модифицированный движок в APK;

3. Создайте пакет исправлений: используйте алгоритм BSdiff для сравнения старого и нового файлов APK и создайте пакет исправлений.

4. Получите доступ к внутреннему интерфейсу при запуске приложения и извлеките пакет исправлений в соответствии с параметрами (номер версии приложения, номер версии пакета исправлений, md5, номер версии flutter SDK, номер версии Engine);

5. Составной пакет патчей: проверьте md5, номер версии приложения, номер версии патча, время установки;

6. Настройте Flutter Engine для загрузки файлов ресурсов libapp.so и flutter_assets по указанному пути;

 

Автор: JD Technology Лю Чжэнчжун, Чжоу Чжи

Источник контента: сообщество разработчиков JD Cloud.

{{о.имя}}
{{м.имя}}

Guess you like

Origin my.oschina.net/u/4090830/blog/9092965