Что знаешь о том, как работает Flutter "под капотом"
Flutter — это UI-фреймворк с открытым исходным кодом от Google, позволяющий разрабатывать кроссплатформенные приложения с единым кодом на языке Dart. Он предоставляет высокую производительность и нативный рендеринг. Чтобы понять, как Flutter работает «под капотом», нужно рассмотреть архитектуру и принципы его работы на разных уровнях: от кода Dart до взаимодействия с платформой и GPU.
🧱 Архитектура Flutter
Flutter использует трёхуровневую архитектуру:
- **Framework (Dart)
** - **Engine (C++)
** - **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
-
Виджет — декларативное описание UI (без состояния).
-
Элемент — живой инстанс виджета (связан с деревом).
-
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 в рантайме
🖼 Отрисовка одного кадра
Цикл рендеринга одного кадра выглядит так:
-
Событие (например, касание) попадает в GestureDetector.
-
Если что-то изменилось, вызывается setState().
-
Flutter вызывает build() → создаёт/обновляет дерево виджетов.
-
Выполняется layout и paint (через RenderObject).
-
Формируется Layer Tree, который отправляется в Skia.
-
Skia рендерит сцену в окно (через OpenGL/Metal).
-
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 рендерится независимо от платформы, с высокой степенью контроля и предсказуемости, но требующей понимания архитектуры и производительности.