Что знаешь о том, как работает Flutter "под капотом"

Flutter — это UI-фреймворк с открытым исходным кодом от Google, позволяющий разрабатывать кроссплатформенные приложения с единым кодом на языке Dart. Он предоставляет высокую производительность и нативный рендеринг. Чтобы понять, как Flutter работает «под капотом», нужно рассмотреть архитектуру и принципы его работы на разных уровнях: от кода Dart до взаимодействия с платформой и GPU.

🧱 Архитектура Flutter

Flutter использует трёхуровневую архитектуру:

  1. **Framework (Dart)
    **
  2. **Engine (C++)
    **
  3. **Embedder (на платформенном языке: Java/Kotlin, Objective-C/Swift, C++ и др.)
    **

1. Framework (уровень Dart)

На этом уровне находятся:

  • Виджеты (StatelessWidget, StatefulWidget, InheritedWidget)

  • Элементы (Element) — узлы дерева, которые связывают виджеты с рендерингом

  • RenderObject — отвечает за отрисовку и layout

  • Animation, Gestures, Routing, Material/Cupertino — всё написано на Dart

Разработчик работает в основном с этим уровнем. Здесь создаются UI-компоненты, управляется состоянием и навигацией.

2. Engine (уровень C++)

Flutter Engine написан на C++ и отвечает за:

  • Рендеринг с использованием Skia (кроссплатформенная графическая библиотека)

  • **Обработку ввода
    **

  • **Сборку кадров
    **
  • **Работу с текстом
    **
  • **Компиляцию AOT и JIT
    **
  • **Работу с Dart Virtual Machine (Dart VM)
    **

Важнейшая роль — отображение UI, который Flutter формирует сам (в отличие от Android, где UI отрисовывается платформенными элементами).

3. Embedder (уровень платформы)

Этот слой:

  • Интегрирует Flutter-приложение с конкретной платформой: Android, iOS, Windows, macOS, Linux, web.

  • Запускает движок Flutter

  • Обеспечивает ввод (клавиатура, мышь, тач)

  • Создаёт окно, OpenGL-контекст (или Metal на iOS)

  • Передаёт события (из платформы во Flutter) и наоборот

Для Android используется FlutterActivity, для iOS — FlutterViewController, и т.д.

⚙️ Как Flutter строит и обновляет UI

  1. Виджет — декларативное описание UI (без состояния).

  2. Элемент — живой инстанс виджета (связан с деревом).

  3. RenderObject — выполняет layout, отрисовку и обработку событий.

Flutter использует двойное дерево: Widget Tree, Element Tree, Render Tree.

Когда вызывается setState():

  • Flutter не обновляет весь UI.

  • Он вызывает build(), пересоздаёт только те виджеты, которые нужно.

  • Сравнивает старые и новые виджеты (reconciliation).

  • Обновляет Element Tree и RenderObject при необходимости.

🎨 Рендеринг через Skia

Flutter не использует системные элементы UI. Вместо этого он сам рисует интерфейс пиксель за пикселем с помощью Skia:

  • Объекты RenderObject выполняют layout

  • Сцена описывается с помощью **Layer Tree
    **

  • Затем слой передаётся в Skia для отрисовки

Всё это рендерится в OpenGL/Metal/Vulkan (в зависимости от платформы).

🧮 Модель исполнения Dart

JIT (Just-In-Time):

  • Используется при разработке (debug mode)

  • Позволяет горячую перезагрузку (hot reload)

  • Быстрая компиляция

AOT (Ahead-Of-Time):

  • Используется при публикации приложения

  • Компилируется в **машинный код
    **

  • Повышает производительность

  • Убирает необходимость Dart VM в рантайме

🖼 Отрисовка одного кадра

Цикл рендеринга одного кадра выглядит так:

  1. Событие (например, касание) попадает в GestureDetector.

  2. Если что-то изменилось, вызывается setState().

  3. Flutter вызывает build() → создаёт/обновляет дерево виджетов.

  4. Выполняется layout и paint (через RenderObject).

  5. Формируется Layer Tree, который отправляется в Skia.

  6. Skia рендерит сцену в окно (через OpenGL/Metal).

  7. GPU показывает кадр.

Цель — уложиться в 16 мс (60 кадров в секунду).

📱 Как Flutter работает с платформенными API

Через платформенные каналы (MethodChannel, EventChannel, BasicMessageChannel):

  • Dart ↔ Native (Android/iOS)

  • JSON-сериализация/десериализация

  • Используется для доступа к камере, Bluetooth, геолокации, системным API и т.д.

Flutter SDK предоставляет множество плагинов, которые используют эти каналы (например, shared_preferences, camera, google_maps_flutter).

📦 Пакеты и плагины

Flutter-проекты используют pub.dev для зависимостей. Плагины бывают:

  • Dart only — работают без нативного кода

  • Platform plugin — включают нативную реализацию (например, через Swift, Java, C++)

🛡 Обработка ввода и жестов

Flutter использует систему Hit Testing:

  • Каждый RenderObject участвует в проверке, был ли он затронут.

  • GestureDetector и Listener обрабатывают события.

  • События обрабатываются в порядке иерархии: от корня к целевому объекту.

🧪 Как работает hot reload

  • Обновляется только дерево виджетов, без перезапуска приложения.

  • Сохраняется состояние (State) виджетов.

  • Код пересобирается в JIT и "вживляется" в рантайм.

Это сильно ускоряет процесс разработки.

🛠 Система сборки

Flutter использует build system:

  • Android: Gradle + Android SDK

  • iOS: Xcode + CocoaPods

  • Web: компиляция Dart в JavaScript (dart2js или dartdevc)

  • Desktop: CMake

📊 Размер приложения

  • Flutter-приложения включают рендеринг-движок внутри APK/IPA.

  • Поэтому минимальный размер около 4–5 МБ даже для простого приложения.

  • В релизе код проходит shrink, tree shaking и obfuscation.

Flutter — это полноценная кроссплатформенная система, в которой весь UI рендерится независимо от платформы, с высокой степенью контроля и предсказуемости, но требующей понимания архитектуры и производительности.