Вышел Flutter 3.47 с рядом заметных изменений.
Главное событие релиза — выход версии 1.0 отдельных пакетов
material_ui и
cupertino_ui.
Это важный шаг, отделяющий дизайн-системы от ядра SDK.
Кроме того, в релизе улучшена производительность и инструментарий в целом. Impeller теперь используется на десктопе по умолчанию, подготовлены пайплайны для iOS, macOS и Xcode 27, а Flutter Widget Previews перешёл в стабильную версию.
Для обновления достаточно выполнить flutter upgrade в терминале —
далее подробнее о ключевых изменениях релиза.
Выбор собственного пути в UI
Сделан первый шаг к декомпозиции Flutter: Material и Cupertino теперь доступны как отдельные пакеты.
Одна из главных сильных сторон Flutter — способность рендерить пиксель-идеальные виджеты Material и Cupertino. Однако из-за того, что эти дизайн-библиотеки исторически были встроены прямо в ядро SDK, их разработка шла медленнее, а вносить изменения или поддерживать актуальность было сложнее.
В текущем релизе ядро SDK всё ещё включает эти библиотеки, но теперь можно
перейти на отдельные пакеты material_ui и cupertino_ui,
которые официально достигли версии 1.0 на pub.dev.
Разделение дорожных карт дизайна (опционально)
Переход на отдельные дизайн-системы даёт контроль над собственной дорожной
картой дизайна. Поскольку material_ui и cupertino_ui
теперь размещены на pub.dev, они могут получать исправления и
новые компоненты по собственному еженедельному графику, независимо от
квартальных релизов Flutter SDK.
Разделение дизайн-систем даёт следующие преимущества:
- Можно использовать последние стили виджетов Cupertino и Material без необходимости обновлять всю версию Flutter SDK.
- Изменения и обновления попадают в релиз быстрее и чаще.
- Закладывается основа для стилистически нейтрального каталога виджетов Flutter, что упростит создание собственных дизайн-систем в будущем.
Как перейти
Для миграции проекта на новые отдельные пакеты нужно выполнить следующую команду:
dart fix --apply --code=migrate_design_widgets
Этот инструмент автоматически обновляет импорты из
package:flutter/material.dart и package:flutter/cupertino.dart
на новые отдельные пакеты.
Примечание: если инструмент миграции столкнётся с проблемами при обновлении
pubspec.yaml(известная на данный момент ошибка), это можно исправить, вручную выполнивflutter pub add material_ui(иcupertino_ui, если он используется), а затем повторно запустивdart fix --apply.
Исходные дизайн-библиотеки внутри ядра SDK планируется официально признать устаревшими в стабильном релизе этой осенью, в ноябре. Если ведётся миграция пакета в экосистеме, переход на отдельные пакеты стоит рассматривать как major-релиз.
Обеспечение совместимости на переходный период
Чтобы упростить переход экосистемы на новые отдельные дизайн-библиотеки,
material_ui и cupertino_ui поставляются с утилитами
миграции. MaterialUiCompatibilityBridge позволяет перевести
приложение на новые пакеты немедленно, даже если часть зависимостей всё ещё
использует старые импорты из ядра SDK.
Например, приложение можно обернуть в мост совместимости:
import 'package:material_ui/material_ui.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF6750A4)),
),
builder: (BuildContext context, Widget? child) {
return MaterialUiCompatibilityBridge(child: child!);
},
home: const HomeScreen(),
);
}
}
Разделение локализаций
В рамках перехода пакет flutter_localizations также был разделён.
Делегаты локализации и переведённые строки для виджетов Material и Cupertino
теперь находятся внутри package:material_ui и
package:cupertino_ui соответственно.
До:
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter/material.dart';
// ...
localizationsDelegates: const <LocalizationsDelegate<dynamic>>[
GlobalCupertinoLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
После:
import 'package:material_ui/material_ui.dart';
// ...
localizationsDelegates: GlobalMaterialLocalizations.delegates,
Установка localizationsDelegates в
GlobalMaterialLocalizations.delegates теперь автоматически
включает делегаты Cupertino и Widgets, упрощая настройку.
Открыто для вклада сообщества
Заморозка изменений в библиотеках Material и Cupertino, введённая ещё в апреле,
позволила обеспечить плавную миграцию. Библиотеки, которые ждут в
material_ui и cupertino_ui, — это те же самые
библиотеки, что уже используются сегодня.
Теперь, когда заморозка снята, в новых пакетах стоит ожидать регулярного выхода исправлений и новых возможностей — релизы планируются еженедельно. Пакеты также официально открыты для вклада сообщества.
Подготовка к новой волне обновлений Apple
С учётом выхода Xcode 27, iOS 27 и macOS 27 этой осенью, значительное внимание было уделено готовности Flutter к предстоящим обновлениям. Чтобы пользователи не столкнулись с сюрпризами в день релиза, рекомендуется протестировать приложения на бета-версиях Apple уже сейчас.
Кроме того, для поддержки Xcode 27 повышены минимальные поддерживаемые версии ОС:
| Платформа | Прежний минимум | Новый минимум (Flutter 3.47+) |
|---|---|---|
| iOS | 13 | 15 |
| macOS | 10.15 | 12 |
Обязательный жизненный цикл UIScene
SDK iOS 27 теперь требует жизненный цикл UIScene для всех
приложений на UIKit. Приложения, собранные с Xcode 27, но не перешедшие
на UIScene, не запустятся.
Для большинства приложений Flutter CLI выполняет эту миграцию автоматически
во время сборки. Однако ручная миграция потребуется, если в
AppDelegate есть собственный нативный код или используются
плагины, всё ещё завязанные на устаревший жизненный цикл приложения.
В таких случаях нужно выполнить миграцию вручную по руководству по переходу
на UIScene/Delegate.
Постепенный отказ от Intel Mac
В соответствии с переходом Apple на Apple Silicon, Flutter постепенно сворачивает поддержку Mac на процессорах Intel. Автоматические тестовые прогоны на Intel-оборудовании отключены, а Flutter CLI теперь выводит предупреждения при сборке на Intel-хостах или при сборке под двойную архитектуру. В будущих релизах эти предупреждения станут ошибками.
Уже сейчас можно перейти на сборку только под ARM64 для macOS-приложений,
выполнив flutter config --enable-macos-arm64-only.
Прогресс Swift Package Manager
Сообщество добилось значительного прогресса в переходе на Swift Package
Manager: 92 из 100 самых популярных iOS-плагинов уже мигрировали.
Если Swift Package Manager был отключён ранее, стоит попробовать снова,
выполнив flutter config --enable-swift-package-manager.
Поскольку CocoaPods сейчас находится в режиме поддержки без активной
разработки, плагины, не перешедшие на SwiftPM, со временем перестанут
работать. Немигрировавшие плагины также получают более низкие оценки на
pub.dev. Авторам плагинов стоит ознакомиться с
руководством по миграции
и предыдущим постом в блоге
для подробностей.
В этом релизе также ускорена сборка благодаря вкладу участника сообщества @lukemmtt, который улучшил пайплайны сборки, отфильтровывая ненужные схемы пакетов SwiftPM на раннем этапе процесса сборки.
Курс на Wasm по умолчанию
Ведётся активная работа по включению WebAssembly (Wasm) по умолчанию для
веб-приложений на Flutter, что приближает производительность в браузере
к нативной. Если веб-приложения ещё не тестировались с Wasm, включить его
можно прямо сейчас, передав флаг --wasm в команду сборки релиза:
flutter build web --release --wasm
При подготовке к этому переходу стоит учитывать, что Wasm требует миграции
кодовой базы на новый пакет для JS-интеропа (package:web),
поскольку устаревшая библиотека dart:html не поддерживается.
Обновление зависимостей пакетов проекта часто автоматически решает эти
проблемы совместимости со старым кодом.
Для более крупных веб-приложений в этом релизе также появилась экспериментальная поддержка отложенной загрузки (deferred loading) для Wasm. Доступная под флагом на основном канале, эта возможность позволяет разбить Wasm-приложение на более мелкие модули с ленивой загрузкой, оптимизируя время начальной загрузки:
flutter build web --release --wasm --enable-wasm-deferred-loading
Современная графика приходит на десктоп с Impeller
Десктопные платформы получают статус полноценных целей для высокопроизводительной графики. В Flutter 3.47 Impeller становится рендерером по умолчанию для macOS, Windows и Linux.
Impeller — рендеринговый движок Flutter следующего поколения, созданный с нуля для замены Skia. Ориентируясь на современные аппаратные API (такие как Metal на macOS и Vulkan на Windows и Linux), Impeller компилирует фиксированный набор шейдеров во время сборки, а не динамически во время выполнения. Это устраняет короткое подёргивание, известное как «jank» компиляции шейдеров, при первом воспроизведении анимации, обеспечивая стабильно плавные переходы с самого первого кадра. Подробнее — в документации рендеринг-движка Impeller.
Чтобы временно отказаться от Impeller, нужно выполнить следующие шаги:
- macOS: установить
FLTEnableImpellerвfalseвInfo.plist. -
Windows: добавить
project.set_impeller_switch(flutter::ImpellerSwitch::Disabled)вmain.cpp. -
Linux: вызвать
fl_dart_project_set_enable_impeller(project, FALSE)вmy_application.cc.
Возможность отката будет удалена в одном из следующих релизов, поэтому, если приходится возвращаться на Skia, стоит завести баг-репорт. Кроме того, на macOS теперь по умолчанию активен режим широкой цветовой гаммы (Wide Gamut Color), обеспечивающий насыщенный, яркий и точный рендеринг цвета на поддерживаемом оборудовании.
Прогресс в экспериментальной работе с несколькими окнами
В партнёрстве с Canonical, благодаря мейнтейнерам @robert-ancell и @mattkae, расширяются экспериментальные API для работы с окнами на десктопе. Linux и Windows теперь поддерживают всплывающие окна, что позволяет создавать нативные контекстные меню и вспомогательные панели инструментов.
Теперь также можно запросить windowHandle у платформенных
контроллеров, чтобы получить прямой указатель на нативное окно
(HWND, NSWindow или GtkWindow).
Это открывает доступ к продвинутым нативным возможностям, таким как
стыкуемые панели (dockable panes) на Windows — вот демонстрация,
подготовленная @orestesgaolin:
Также устранено несколько ошибок с фокусом и реализацией окон. На Windows активация окна больше не выводит фоновые окна на передний план и не крадёт фокус при возвращении в приложение — исправление внёс участник сообщества @9AZX:
На Linux при создании нескольких окон теперь явно выполняется их реализация до получения первого кадра от композитора, что устраняет ранние предупреждения рендеринга и ассерты композитора.
Также добавлен новый API для автоматического размера по содержимому, позволяющий создавать обычные и диалоговые окна, которые автоматически подстраиваются под размер содержимого.
Флейворы для десктопа
Windows и Linux теперь поддерживают флейворы (flavors) Flutter.
Например, файл pubspec.yaml может использовать разные ресурсы
для разных флейворов:
flutter:
assets:
- path: assets/flavor_a/images
flavors:
- flavor_a
- path: assets/flavor_b/images
flavors:
- flavor_c
Для указания флейвора используется опция --flavor. Например:
flutter build windows --flavor flavor_aflutter build linux --flavor flavor_a
Благодарность @AngeloAvv за замечательный вклад!
Более чёткий текст на десктопе
Десктопные экраны часто имеют меньшую плотность пикселей по сравнению с мобильными дисплеями, но обладают большей вычислительной мощностью для графики. Чтобы обеспечить более чёткий текст и гладкие векторные кривые на десктопе, движок Flutter на базе Impeller теперь использует рендеринг по методу функции знакового расстояния (Signed Distance Function, SDF) на macOS, Linux и Windows.
Стабильные превью и обновления GenUI
Widget Preview переходит в стабильную версию
Flutter Widget Preview теперь стабилен: он позволяет мгновенно рендерить, исследовать и итеративно доработывать отдельные компоненты UI без сборки или запуска всего приложения.
С этим стабильным релизом доступно следующее:
-
Более быстрый запуск благодаря локальному кешированию проекта в папке
.widget_preview/, что устраняет повторные накладные расходы на настройку. -
Более гибкое тестирование благодаря абстрактному API
PreviewThemeData, поддерживающему последовательное наслаивание тем для сложных матричных тестов. -
Автоматическая синхронизация веб-ресурсов при просмотре веб-виджетов:
ресурсы
web/из основного проекта копируются напрямую, применяя любую кастомную тему или настройкиindex.htmlпри использовании Flutter web автоматически.
Дальнейшее развитие GenUI
Экосистема Flutter продолжает развиваться, чтобы удовлетворять потребности
разработчиков, использующих GenUI для создания новых видов агентных
интерфейсов для пользователей. Недавно вышла версия 0.10.0 пакета
genui, принесшая ряд исправлений и новых возможностей, среди которых:
-
Новый пакет
a2ui_core, централизующий классы, связанные с протоколом, включая выражения, записи каталога и другое. - Поддержка клиентских функций A2UI, которые позволяют предоставить агенту функции, которые он может направить клиенту использовать для валидации, вычисляемых значений и других небольших задач без обращения по сети.
Улучшение платформенного опыта
Отдельный раздел посвящён точечным улучшениям от сообщества и команды Flutter, отшлифовавшим опыт разработчиков и пользователей на всех платформах.
Android
На Android устранена проблема виртуальной клавиатуры, при которой модификаторы (например, Shift) могли «застревать» во время событий. Обработчик клавиш теперь пропускает синтез физических клавиш для ввода с виртуальной клавиатуры, обеспечивая чистое взаимодействие с клавиатурой.
Матрица зависимостей Android
Для обеспечения стабильных сборок Flutter 3.47 проверен на следующих версиях зависимостей Android:
- Java: 17 (минимально требуемая версия)
- Kotlin Gradle Plugin (KGP): 2.4.0
- Android Gradle Plugin (AGP): 9.1.0 (новейшая, совместимая с KGP 2.4.0)
- Gradle: 9.3.1 (минимум для AGP 9.1.0)
Чтобы обеспечить успешную сборку приложения в будущих релизах, рекомендуется использовать стандартные переменные уровня API, предоставляемые Flutter SDK, в файлах сборки. В этом релизе они настроены со следующими значениями по умолчанию:
flutter.compileSdkVersion(API 36)flutter.targetSdkVersion(API 36)flutter.minSdkVersion(API 24)
iOS и macOS
Для разработчиков под iOS повышена прозрачность подписи кода. Благодаря участнику сообщества @alex-medinsh CLI теперь отображает как Team ID, так и название команды при выборе сертификата.
Кроме того, участник сообщества @mozammal-hossain улучшил диагностику, добавив более понятные сообщения об ошибках provisioning-профиля при сбое подписи.
Десктоп
Десктопные платформы также получили точечные улучшения. Решена проблема
с позиционированием курсора при вводе корейского текста на Windows
(благодаря @CHOIgoung), а плагины
для Windows теперь могут выносить затратные задачи из потока платформы,
используя FlutterEngine::PostPlatformThreadTask. На Linux
@CodeDoctorDE добавил поддержку
отслеживания поворота и нажима стилуса.
Графика и движок
В движке фрагментные шейдеры, ориентированные на OpenGLES, больше не требуют условного отражения координат при чтении текстур — теперь это обрабатывается в вершинном шейдере. Подробности — на странице об этом breaking change для рендеринга в текстуру на OpenGLES.
Доработки фреймворка
Наконец, сам фреймворк стал более плавным благодаря улучшениям в ключевых компонентах:
Доступность и семантика: настройки высокого контраста и
инверсии цвета на Android теперь определяются автоматически благодаря
@xxxOVALxxx
(MediaQueryData.highContrast и MediaQueryData.invertColors).
Вложенные текстовые фрагменты внутри Text.rich теперь
соответствуют последовательности их размещения в дереве семантики,
а также добавлена блокировка фокуса клавиатуры для BlockSemantics.
Текст и выделение: маркеры выделения текста на мобильных устройствах теперь остаются стабильными при небольшом скролле, а клавиатурные сочетания могут закрывать открытые меню выделения. На Android маркеры выделения больше не перекрывают контекстное меню при расположении у верхней границы экрана — благодаря @JhonaCodes.
| ДО | ПОСЛЕ |
|---|---|
|
|
Также исправлен сбой в SelectableRegion при начале выделения
в пустом скроллируемом контейнере и устранены визуальные артефакты
подсветки на выцветшем выделяемом тексте — благодаря
@ikramhasan.
| ДО | ПОСЛЕ |
|---|---|
|
![]() |
Жесты и скроллинг: улучшена передача жестов для нативных
представлений iOS, встроенных через platform views.
EdgeDraggingAutoScroller теперь учитывает ScrollPhysics
активного скроллируемого представления, предотвращая автоскролл на
заблокированных списках.
Улучшения базовых виджетов: сохранение исходных цветов
внутри ImageIcon с помощью useOriginalColors: true,
указание поведения клиппинга в AnimatedCrossFade и
отслеживание ошибок потока изображений напрямую через
ImageStreamListener.
Готовы к обновлению
Всё готово — осталось лишь применить эти обновления на локальной машине:
flutter upgrade
Пока SDK обновляется в фоне, есть небольшое домашнее задание (из приятных):
- Познакомиться с контрибьюторами: посмотреть новую серию видео Introducing: Flutter Notable Commits, посвящённую участникам сообщества, благодаря которым состоялся этот релиз.
- Изучить детали: пробежаться по странице breaking changes, чтобы быть готовым к миграции на отдельные UI-пакеты.
Остаётся с интересом ждать, что сообщество создаст с этой новой, улучшенной версией Flutter.
