⚙️ Исправлена ошибка аттача контроллера к драйверу после тайпкаста
Подробности о самом интересном:
🔥 Среди новых виджетов есть совершенно особенный - RemoteSubtree. Этот виджет позволяет динамически загружать собственный контент (макет дочерних поддеревьев виджетов). Ключевая фича виджета - возможность передать ему список зависимостей (по аналогии с действиями), благодаря которым будут собраны данные виджетов и переданы в теле запроса на получение контента.
🚀 Экспорт API duit_kernel, который отвечает за работу тем. С этого релиза этой функцией можно уверенно пользоваться! В example app добавлен пример использования нового API.
🎁 Работа с кастомными виджетами стала еще более удобной! Больше не требуется вручную кастовать UIElementController<dynamic> к UIElementController<тип_атрибута> - приведение типов будет выполенено автоматически.
Уже в эту пятницу, 21 февраля, в Москве пройдет FlutterConf — профессиональная конференция по Flutter. Ожидается, что соберется больше двухсот специалистов — докладчиков и слушателей.
Доклады будут читаться в два потока, тематика достаточно широкая: реальные кейсы с нестандартными требованиями, архитектурные решения и инструменты для Flutter-проектов. Выступать будут разработчики и тимлиды из Amiga, Яндекс-Про, Билайна, Лаборатории Касперского, Потока, Открытой мобильной платформы, Friflex, MadBrains, BetBoom.
А в шесть часов вечера начнется круглый стол, посвященный прошлому, настоящему и будущему Flutter.
Посмотреть расписание конференции и зарегистрироваться можно на сайте (регистрация платная), посетить ее можно в Москве в Radisson Blu Belorusskaya Moscow или же подключиться удаленно.
От «Финама» мы отправим туда нескольких выразивших желание разработчиков из Москвы, а также будем смотреть мероприятие в Питере, в коворкинге. Наша команда работает с Flutter с 2019 года, наши приложения выигрывают премии на тематических мероприятиях. Кстати, прямо сейчас у нас открыта вакансия Flutter-разработчика, и, если кому-то из хабравчан интересно – написать можно нашему рекрутеру.
Официальное объявление от команды Dart: разработка макросов остановлена.
После нескольких лет экспериментов выяснилось, что их реализация слишком сильно замедляет компиляцию и ухудшает разработческий опыт (о чем не раз писал и говорил на Crossconf 2024). У меня были предположения, что мы увидим макросы только в 2026-м году, но такого поворота событий совсем не ожидал >_<
Конечно, это не повод ставить крест на Dart, хотя и очень обидно! 😭 Вместо макросов команда сосредоточится на:
Улучшении работы с данными – это самая востребованная фича среди разработчиков.
Оптимизации build_runner – ускорение сборки и улучшение генерации кода.
Внедрении augmentations – новый инструмент, который упростит кодогенерацию.
👉 Подробнее об этом можно прочитать в статье на Medium, которую написал директор по разработке Dart и его экосистемы Vijay Menon
Что думаете по этому поводу? Какие в таком случае новые фичи ждете? Разочарованы ли отменой макросов?
Разрозненная структура файлов, разные подходы к оформлению и дублирование функциональности — всё это замедляет разработку и повышает вероятность ошибок. Чтобы победить хаос, сделать работу команды быстрее и проще, попробуйте внедрить CodeStyle — это свод правил, которые делают код читаемым, стандартизированным и удобным для поддержки.
Вот что вы получите:
Читаемость: новые участники команды быстрее понимают проект.
Стандартизация: вся кодовая база выглядит так, будто ее писал один человек.
Поддерживаемость: проще рефакторить и находить ошибки.
Почему CodeStyle особенно важен для Flutter
Flutter на проектах дает гибкость, которая при отсутствии дисциплины превращается в проблему. Например, вы можете столкнуться с:
разрозненной структурой файлов, которая затрудняет поиск компонентов;
непоследовательным оформлением кода, которое усложняет его понимание;
дублированием библиотек и функционала, которое приводит к путанице.
Единый CodeStyle решает эти проблемы и создает прозрачную и предсказуемую структуру проекта.
Как внедрить CodeStyle: 4 шага
1. Обучение
Проводите мастер-классы и лекции, показывайте примеры из реальных проектов. Это помогает разработчикам видеть преимущества стандартов.
2. Автоматизация
Настройте инструменты для проверки кода:
линтеры (например, flutter_lints) для автоматической проверки стиля;
pre-commit хуки (Husky или Lefthook) для форматирования кода перед коммитом.
3. Код-ревью
Сделайте ревью обязательным этапом Pull Request. Это улучшит качество кода и поможет следить за соблюдением правил.
4. Командное соглашение
Создайте документ с правилами CodeStyle и внедрите их в культуру команды. Пусть разработчики понимают, что стандарты упрощают жизнь каждому.
Если хотите внедрить эти подходы на своих проектах, читайте подробную статью от нашего Flutter-разработчика Никиты Грибкова. В ней найдете больше примеров, кода и рекомендаций.
Прошедшее мероприятие от команды Flutter - #FlutterInProduction можно разбить на 3 части (если лень читать - вот ссылки на видеоразбор мероприятия ЮТУБВК)
👉 Разговор про эры развития Flutter:
эра экспериментов (2014 - 2018)
эра роста ( 2018 - 2022)
Эра кровавого энтерпрайза (начиная с середины 2022 года)
Разработчики наконец-то определились со зрелостью фреймворка и на протяжении этой части (да и всего мероприятия) нам показывали, что Flutter применяется в разных областях и крупными компаниями с огромнейшим потоком клиентов ^_^
👉 Экосистема
Тут было про поддержку различных IDE, что на pub доступны более 50к пакетов. Заострили внимание на том, что вокруг Flutter выстраивается экосистема (FlutterFlow, Shorebird, Serverpod, Codemagic), в то время как он сам по гланды интегрирован в экосистему Google☝️
Отдельно следует отметить упоминание о Flutter Consultants, что говорит о реальной зрелости фреймворка😎
👉 Если обобщить все услышанное с секцией Roadmap, получится следующая выжимка над чем будет работать команда Flutter в 2025 году:
👀 Точность воспроизведения платформ. Такое обновление виджетов, чтобы у людей не складывалось ощущение, что это Flutter
🔥 Impeller (Flutter GPU) не только на мобилках, но и на десктопе (web пока под большим вопросом)
🔥🎉🥳 Средства предварительного просмотра виджетов с поддержкой редактирования
🔥🎉🥳 Прямое взаимодействие с native platform
🔥🔥🔥 Ускорение написания и упрощение чтение кода (p.s. это подгорает мой пердак от увиденных декораторов 😂, первичный конструктор - норм тема😎)
Не все показанное может быть реализовано на 100% От некоторых фич могут отказаться или перенести на потом.
Прошедшее мероприятие от команды Flutter - #FlutterInProduction можно разбить на 3 части (если лень читать - вот ссылки на видеоразбор мероприятия ЮТУБВК)
👉 Разговор про эры развития Flutter:
эра экспериментов (2014 - 2018)
эра роста ( 2018 - 2022)
Эра кровавого энтерпрайза (начиная с середины 2022 года)
Разработчики наконец-то определились со зрелостью фреймворка и на протяжении этой части (да и всего мероприятия) нам показывали, что Flutter применяется в разных областях и крупными компаниями с огромнейшим потоком клиентов ^_^
👉 Экосистема
Тут было про поддержку различных IDE, что на pub доступны более 50к пакетов. Заострили внимание на том, что вокруг Flutter выстраивается экосистема (FlutterFlow, Shorebird, Serverpod, Codemagic), в то время как он сам по гланды интегрирован в экосистему Google☝️
Отдельно следует отметить упоминание о Flutter Consultants, что говорит о реальной зрелости фреймворка😎
👉 Если обобщить все услышанное с секцией Roadmap, получится следующая выжимка над чем будет работать команда Flutter в 2025 году:
👀 Точность воспроизведения платформ. Такое обновление виджетов, чтобы у людей не складывалось ощущение, что это Flutter
🔥 Impeller (Flutter GPU) не только на мобилках, но и на десктопе (web пока под большим вопросом)
🔥🎉🥳 Средства предварительного просмотра виджетов с поддержкой редактирования
🔥🎉🥳 Прямое взаимодействие с native platform
🔥🔥🔥 Ускорение написания и упрощение чтение кода (p.s. это подгорает мой пердак от увиденных декораторов 😂, первичный конструктор - норм тема😎)
Не все показанное может быть реализовано на 100% От некоторых фич могут отказаться или перенести на потом.
Hola, Amigos! Делюсь с вами записью своего доклада с конференции Mobius на тему «Создание indoor-карты здания на Flutter». Рассказал, как реализовать размещение на одном или нескольких экранах внутренней карты здания. А также раскрыл подходы и собственное решение с использованием Flutter.
Hola, Amigos! На связи Павел Гершевич, Flutter Team Lead в Amiga. Сегодня поговорим про отображение HTML-тегов как виджетов в наших приложениях на Flutter.
Чаще всего для этого используется библиотека flutter_html:
Html(data: ‘<p>Hello World</p>’);
Но у нее есть несколько минусов:
– Она больше года не обновлялась, что с одной стороны хорошо, так как она стабильна, а с другой — она уже устаревает. –В ней есть баги. Например, если внутри тега <p> окажется список (<ul>, <ol>), то снизу появляется отступ, равный высоте списка. – Не очень понятная система стилизации. Чтобы что-то изменить, нужно разобраться, как это делается, так как вместо CSS-атрибутов используются собственные подходы.
Пример стилизации, где нужно поменять размер шрифта для всего документа:
Столкнувшись с этими минусами, мы решили перейти на вторую по популярности библиотеку — flutter_widget_from_html_core. Во-первых, она лишена вышеописанных багов. Во-вторых, она модульная, и к ней можно многое прикрутить.
HtmlWidget(‘<p>Hello World</p>’);
Со стилями всё интереснее. Шрифт устанавливается через стандартный TextStyle:
...,
textStyle:
TextStyle(...),
);
Но если нужно его раскрасить или что-то ещё, всё становится сложнее. Продолжение по ссылке.
Преимущества Rive при разработке Flutter-приложений
При разработке Flutter-приложений используют много типов анимации, о чем мы ранее уже писали. Но Rive всё-таки превосходит большинство из них. Во-первых, у него удобный встроенный UI-интерфейс. Во-вторых, в Rive есть раздел Community, где авторы выкладывают бесплатные анимации.
В-третьих, — и это главное преимущество — в Rive есть State Machine. Это визуальный способ связать анимацию воедино и определить логику, которая управляет переходами. State Machine позволяет создавать интерактивную графику движения, готовую к внедрению в ваш продукт, приложение, игру или веб-сайт.
State Machine включает несколько уровней:
Graph — пространство, в котором мы добавляем состояния и соединяем переходы.
State — анимации временной шкалы, которые могут воспроизводиться в нашей машине состояний.
Transaction — переходы представляют собой логическую карту для State Machine.
Inputs — договор между дизайнерами и разработчиками. Как дизайнеры, мы используем входы как способ управления переходами в нашей машине состояний, назначая их в качестве условий. Разработчики связываются с входами во время выполнения и определяют условия с помощью кода, который может изменить эти входы.
Layers — слой State Machine, который позволяет воспроизводить одну анимацию за раз.
Подробнее о том, как работает Rive и как интегрировать его в проект, в нашем блоге.
Изменения в скролле. Тут завезли оптимизацию и гибкость в управление поведением.
Виджет AnimationStyle. Он позволяет юзерам менять стандартное поведение анимации в виджетах. А разработчики с его помощью могут переопределять кривые и продолжительность анимации.
Adaptive Switch. Компонент выглядит и ведет себя как нативный на macOS и iOS, а в других случаях — как Material Design. При этом он не зависит от библиотеки Cupertino, поэтому у него один и тот же API на всех платформах.
Существует много типов анимации для Flutter-приложений. Среди них — Rive-анимация, Hero animations, Progressindicator и т. д. С их помощью можно создавать кастомную анимацию для любого вида работ с системой. Но наиболее базовое решение — библиотека Animations.
Она предоставляет стандартные анимации Material Design. Система движений Material Design состоит из четырех паттернов для перехода между компонентами. Вот они:
Container Transform. Он предназначен для переходов между элементами интерфейса, включающими контейнер. Паттерн создает видимую связь между этими элементами.
Shared Axis. Его используют для переходов между элементами пользовательского интерфейса, имеющими пространственную или навигационную связь. Паттерн использует общую трансформацию по осям X, Y или Z для усиления взаимосвязи между элементами.
Fade Through. Его используют для переходов между элементами интерфейса, не имеющими тесной связи друг с другом.
Fade. Он для элементов интерфейса, которые входят или выходят за границы экрана. Например, диалог, который появляется и исчезает из центра экрана.
В шаблонах Shared Axis и Fade Through также нужно использовать библиотеки для навигации. В нашем случае это go_router. В Container Transform и Fade навигацию можно не использовать.
Начинающие Flutter-разработчики не всегда понимают, для чего нужно ключевое слово yield в Dart. Оно используется в генераторах Stream для пошаговой передачи данных. Это полезно в BLoC для управления состояниями и событиями.
Примеры использования yield в Dart:
1. Простой генератор:
Stream<int> countStream(int to) async* {
for (int i = 1; i <= to; i++) {
yield i; // Постепенно выдаёт числа от 1 до to
}
}
Так мы можем создать поток, который поочередно выдает числа от 1 до указанного значения.
2. Использование в BLoC
class CounterBloc extends Bloc<CounterEvent, CounterState> {
@override
CounterState get initialState => CounterInitial();
@override
Stream<CounterState> mapEventToState(
CounterEvent event,
) async* {
if (event is Increment) {
yield CounterLoading();
// Представим, что здесь какая-то асинхронная логика
yield CounterLoaded(newState);
}
}
}
Здесь yield используется для отправки различных состояний (например, загрузки и загруженного состояния) в ответ на события.
yield во Flutter — это мощный инструмент для создания асинхронных потоков данных и управления состояниями в BLoC. Он делает код более чистым, понятным и поддерживаемым. А если говорить совсем просто, то yield добавляет значение к выходу потока функции async*. Это как return, но он не завершает функцию.
Нижний Новгород • Екатеринбург • Новосибирск • Владивосток • Ижевск • Казань • Тюмень • Уфа • Иркутск • Челябинск • Самара • Хабаровск • Красноярск • Омск
Как часто вы сталкивались с проблемой изменения данных, переданных в качестве параметра? Иллюстрация:
int getCountBagel(List<String> list) {
list.retainWhere((e) => e == '?');
return list.length;
}
main() {
final basket = ['?', '?', '?', '?', '?'];
final countBagel = getCountBagel(basket); // 2
print(basket); // [?, ?]
}
Выполнив копирование getCountBagel([...basket]), вы обезопасите себя. Да, это ужасный способ посчитать количество элементов. Но представьте, что вы зависите от стороннего api, к которому у вас нет непосредственного доступа.
Обратная задача: в Dart примитивные типы всегда передаются по значению. Это означает, что если вы передаёте экземпляр примитивного типа в качестве параметра в функцию (или класс) и внутри его изменяете, то оригинальный экземпляр останется неизменным:
void increase(int i) => i++;
main() {
int i = 0;
increase(i);
print(i); // 0
}
Если вы хотите передать что-то по ссылке, то заверните это в класс:
class Wrapper {
Wrapper(this.i);
int i;
}
void increase(Wrapper w) => w.i++;
main() {
final w = Wrapper(0);
increase(w);
print(w.i); // 1
}
но такой способ ухудшит SRP (принцип единой ответственности) и усложнит тестирование функции increase... Ответ в комментарии ?
Важность unit и интеграционных тестов несомненна для более-менее опытного разработчика. В этом посте поделюсь как решить следующую задачу: Дано:
1) endpoint api для которого нужене OTP (one time password)
2) QR код экспорта из google authenticator
Найти: автоматически получать OTP и отправлять его endpoint-у
Решение:
1) Сканируем QR код любым сканером QR кодов, получаем что-то вроде 'otpauth-migration://offline?data=CjIKFEuKYhr.....' , обозначим это за url. 2) Этот url надо раскодировать, есть несколько вариантов как это сделать привожу довольно просто (минимум телодвижений) https://github.com/qistoph/otp_export . Клонируем и выполняем команду ./parse.py 'url' вывод будет содержать secret это Base32 строчка-ключ обозначим за secret.
3) Осталось выбрать библиотеку для вашего языка реализующую RFC4226/RFC6238 и с помощью sercret и текущего времени в мс. получить OTP
Привожу пример на dart : Пакет https://pub.dev/packages/otp Вызов: final code = OTP.generateTOTPCodeString(secret, date.millisecondsSinceEpoch,algorithm: Algorithm.SHA1, isGoogle: true);
В Dart 3.0 появились Switch expressions, что позволяет сразу получить значение на основе выражения. Это может выглядеть так:
var x = switch (y) { ... };
print(switch (x) { ... });
return switch (x) { ... };
Сейчас я расскажу, какие преимущества даст новый подход. ?
habr...
Теперь, когда мы получили погодные данные (Pop.medium и temp = 17.0 ) из приложения Weather Today, наш код будет выглядеть следующим образом:
/// Probability of precipitation
enum Pop { low, medium, high }
enum Things {
umbrella, // зонт
raincoat, // дождевик
windbreaker, // ветровка
glasses, // очки
;
List<Things> takeExtra(double temp /*Celsius*/, Pop pop) {
return ...;
}
}
Для удобства я определил метод takeExtra внутри enum, чтобы иметь доступ к значениям без использования Things. всякий раз. Подумайте, как бы вы реализовали данный метод.
Заметьте, это выглядит достаточно ёмко и выразительно. Страшно представить, какая цепочка switch case и if'ов могла выстроиться в этом методе. И всё же, используйте с умом данное новшество – лучше написать понятней, чем вычурней.
Unhandled Exception: Unsupported operation: Cannot modify an unmodifiable list
Неизменяемый список создан, что очень хорошо, однако, здесь есть подводные камни. Сложность алгоритма для List.unmodifiable – O(n), а для UnmodifiableListView – O(1)? Почему?