TGViewer
Channel Public Channel
Flutter & Dart | Мобильный трудоголик

Flutter & Dart | Мобильный трудоголик

@hardworkerflutter

Пишу простым языком про разработку на Flutter & Dart (iOS, Android, macOS, Windows) и мобильную разработку в целом.
Обо мне: https://t.me/hardworkerFlutter/2
Чат: @flutterDevChat
Другие мои каналы: @hardworkerIT и @itDenisov
Subscribers
405
Photos
29
Videos
1
Links
82

Showing posts older than #72 · Back to latest

Older Posts 20 shown
Post #71 783
👣 Как правильно делать задержку в Flutter и не блокировать интерфейс

Во Flutter, как и в любом другом фреймворке, периодически возникает задача сделать задержку в выполнении кода. На первый взгляд кажется, что можно просто взять и приостановить выполнение на пару секунд. Но если сделать это напрямую, интерфейс просто перестанет реагировать на касания.

Давайте разберемся почему так происходит и как делать задержки правильно.


Почему нельзя блокировать основной поток:

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

На андроиде если заблокировать главный поток больше чем на 5 секунд, система вообще предложит пользователю закрыть приложение. На iOS такого жесткого порога нет, но интерфейс все равно перестает реагировать, что мгновенно портит пользовательский опыт.

Поэтому все, что может занять время, нужно выполнять асинхронно, чтобы основной поток оставался свободным для отрисовки и обработки ввода.


Как правильно сделать задержку во Flutter:

Во Flutter есть несколько способов сделать асинхронную задержку. Самый простой и правильный - использовать Future.delayed():


Future.delayed(Duration(seconds: 2), () {
// код, который выполнится через 2 секунды
});


Этот метод возвращает Future, который завершится через указанное время. Все это время основной поток продолжает работать, интерфейс остается отзывчивым, а через 2 секунды выполняется переданный код.

Если нужно подождать внутри асинхронной функции, используется await:


void doSomething() async {
await Future.delayed(Duration(seconds: 2));
// код после задержки
}



Когда еще может понадобиться задержка:

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

Например после того как пользователь что-то отправил, можно показать иконку успеха, а через полторы секунды автоматически закрыть экран. Или сделать паузу между шагами в обучающем процессе.

Во всех этих случаях Future.delayed() - оптимальный выбор.


Чего делать не стоит:

Самый простой и опасный способ сделать задержку - использовать sleep(). Это синхронная блокировка текущего потока на указанное время. Если вызвать ее на главном потоке - интерфейс полностью перестанет реагировать на касания.

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


Если нужно больше контроля - Timer:

В некоторых сценариях Future.delayed() не подходит. Например, если нужно выполнять действие периодически, отменять его или запускать несколько раз с интервалом.

Для этого во Flutter есть класс Timer:


Timer(Duration(seconds: 2), () {
// выполнится один раз через 2 секунды
});


И для периодического выполнения:


Timer.periodic(Duration(seconds: 2), (timer) {
// будет выполняться каждые 2 секунды
});


Timer работает асинхронно и не блокирует UI. Его легко отменить, вызвав timer.cancel().


🔗 Читать подробнее


💡 Вывод:

Для создания задержек во Flutter используйте асинхронные методы Future.delayed() или Timer. Они не блокируют основной поток, интерфейс остается отзывчивым, а пользователь не видит зависаний.

Использование синхронных задержек на главном потоке почти всегда приводят к ошибкам. В мобильной разработке зависший интерфейс для пользователя равноценен сломанному приложению. Даже если внутри все работает, внешне он этого не видит.


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик

Закрытый канал:
🚀 Мобильный трудоголик PRO
  • 👍 4
  • ❤ 1
Post #70 1.72K
👣 GenUI в действии: команда Flutter раздала 3000 чашек кофе с ИИ-рисунками на пенке

Команда Flutter решила поделиться опытом создания необычного демо-проекта, который они показали посетителям Google Cloud Next и Google I/O. В статье разработчики рассказывают, как построили приложение для кофейни, где каждый посетитель мог заказать латте с изображением, сгенерированным нейросетью прямо на пенке. Проект назывался GenLatte. За два мероприятия команда раздала 3000 чашек.


Как это работает:

На первый взгляд все просто. Посетитель подходил к киоску, открывал веб-версию Flutter-приложения и описывал свое место мечты. Это могло быть что угодно: домик у озера, снежный лес, закат на пляже. Промпт ограничивался 50 символами, чаще всего это было одно-два слова.

Дальше в дело вступала нейросеть Nano Banana. Система брала короткую фразу и разворачивала ее в полноценный промпт для генерации изображения. При этом создавалось сразу четыре варианта картинки, все разные по композиции и настроению. Пользователь выбирал понравившийся и изображение отправлялось на печать на пенке латте.


Персонализация через GenUI:

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

Gemini предварительно подготавливал четыре вопроса о том, как можно изменить изображение. Например, для домика у озера это могли быть вопросы о времени суток, погоде, наличии людей или конкретных деталях. В зависимости от выбранного типа вопроса система подставляла разные элементы управления: текстовое поле для открытых вопросов или кнопки для выбора из вариантов.

Это и есть GenUI в действии - интерфейс, который собирается на лету под конкретную задачу.

После того как пользователь отвечал на вопросы, система отправляла обновленный промпт обратно в Nano Banana и генерировалась новая версия изображения. Все это происходило в реальном времени.


Техническая архитектура:

Проект построен на Flutter и Firebase. Вся логика собрана в монорепозитории, где объединены Flutter-приложение, Firebase-бэкенд и общий код для бизнес-логики. Такой подход позволил избавиться от дублирования зависимостей, переиспользовать код и выполнять атомарные деплои.

Внутри самого Flutter-приложения было реализовано пять отдельных экранов:

🔵Экран заказа для посетителей.

🔵Экран бариста с актуальными заказами.

🔵Экран модератора для проверки безопасности контента.

🔵Экран очереди для ожидающих.

🔵Экран с недавними заказами в виде плавающих пузырьков.


🔗 Читать подробнее


💡 Вывод:

GenLatte - это не просто забавный демо-проект. Это показательный пример того, как Flutter, Firebase и генеративный ИИ работают вместе в реальных условиях. 3000 чашек кофе - это не шутка. Проект показал, что с помощью Flutter можно быстро собирать сложные мультиплатформенные приложения, а Firebase закрывает все вопросы с бэкендом и масштабированием. И главное - GenUI перестает быть абстрактной концепцией. Приложение само решало, какой интерфейс показать пользователю в ответ на его действия.

Конечно, код проекта доступен в репозитории flutter/demos, но авторы предупреждают: он не поддерживается и предназначен только для вдохновения. А вдохновения там действительно много. Когда в ближайшее время задумаетесь о том, как можно применить генеративный ИИ в своем проекте - вспомните историю о латте с нейросетевым рисунком. Это хорошая иллюстрация того, насколько широко могут разойтись технологии, которые вчера казались просто игрушками.


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик
  • 👍 3
  • ❤ 1
Post #69 748
👣 Container vs SizedBox во Flutter: в чем разница и когда использовать

Привет! Во Flutter есть два виджета, которые на первый взгляд делают одно и то же: Container и SizedBox. Оба управляют размерами и расположением дочерних виджетов. Но между ними есть принципиальная разница и использование не того виджета в нужном месте может привести к лишней вложенности, нечитаемому коду и проблемам с производительностью.


Что такое Container:

Container - это универсальный виджет, который объединяет в себе несколько функций: управление размерами, отступами (padding и margin), фоном, рамкой и тенью. Он может одновременно задавать ширину, высоту, цвет, скругление углов и отступы внутри себя.

Container удобен, когда нужно настроить внешний вид блока: задать фон, обрезать по краям, добавить отступы. Он умеет адаптироваться под размеры дочернего виджета, если явно не заданы ширина и высота.


Что такое SizedBox:

SizedBox - это простой и легкий виджет. Он делает только одно: задает фиксированный размер. Либо ширину, либо высоту, либо оба параметра сразу. Если ему не передать child, он просто создаст пустое пространство заданного размера - это удобно для создания отступов между виджетами, альтернатива использованию Padding или Spacer.

SizedBox не умеет работать с фоном, рамками, тенями или отступами. Его задача - только размер.


Ключевые отличия:

Container может существовать без явно заданных размеров и растягиваться по содержимому. SizedBox всегда либо фиксированного размера, либо, если размер не указан, вообще ничего не отображает.

Container - тяжелый виджет. Он создает больше объектов и выполняет больше вычислений. SizedBox - легкий, он просто передает свои ограничения дочернему виджету.

Container - для стилизации. SizedBox - для контроля размера.


Когда использовать SizedBox:

SizedBox лучше использовать в трех случаях:

🔵Когда нужно задать фиксированные ширину или высоту без дополнительной стилизации.

🔵Когда нужно добавить пустое пространство между виджетами.

🔵Когда вы явно ограничиваете размеры дочернего виджета, не добавляя при этом никаких декоративных элементов.


Когда использовать Container:

Container подходит для всего остального:

🔵Когда нужно не только задать размер, но и добавить фон, рамку, тень или скругление.

🔵Когда нужны внутренние отступы.

🔵Когда нужно, чтобы виджет сам подстраивался под контент и при этом имел декоративное оформление.


🔗 Читать подробнее


💡 Вывод:

Container и SizedBox - разные инструменты для разных задач. SizedBox - это про размеры и пустые пространства, Container - про внешний вид и универсальность. Не используйте Container там, где достаточно SizedBox, и не пытайтесь стилизовать SizedBox - он для этого не предназначен.

И главное: не превращайте верстку в матрешку. Если видите лишнюю вложенность - пересмотрите выбор виджета. Чистый и читаемый код - это не только про логику, но и про правильно подобранные строительные блоки.


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик

Закрытый канал:
🚀 Мобильный трудоголик PRO
  • 👍 3
  • ❤ 2
  • 🗿 1
Post #68 1.83K
👣 Почему Flutter - идеальный выбор для разработки с ИИ-агентами

Привет. В последнее время все только и говорят о разработке с помощью ИИ-агентов. Кто-то в восторге, кто-то скептичен. Но мало кто задумывается, как выбор технологий влияет на эффективность работы с LLM. Майкл Томсен, инженер из команды Flutter, выпустил разбор на эту тему. Он объясняет, почему мультиплатформенная архитектура Flutter дает неожиданные преимущества в эпоху агентской разработки. Основная мысль простая: одна кодовая база вместо трех - это не только удобно для людей, но и критически важно при работе с ИИ.


В чем была ценность Flutter раньше:

Еще до эры агентов Flutter решал классическую проблему: вместо трех команд (iOS, Android, веб) можно иметь одну, которая пишет код на Dart и запускает его везде. От 95% до 99% кода в реальных проектах переиспользуется. Это давало:

🔵Быстрый выход на рынок на всех платформах.

🔵Гарантированную консистентность фич и дизайна.

🔵Нативную производительность (компиляция в машинный код).

🔵Безопасность благодаря строгой типизации Dart.


Что изменилось с приходом ИИ-агентов:

Когда разработкой занимаются агенты, нативный подход (Swift под iOS, Kotlin под Android, JavaScript под веб) начинает пробуксовывать. Агенту нужно сгенерировать одну и ту же логику трижды, на разных языках, с разными нюансами. Это приводит к трем проблемам.

Во-первых, растет потребление токенов. Каждая генерация и каждое исправление умножаются на количество платформ. Во-вторых, возникают отличия в реализации между платформами. Агент может начать галлюцинировать и на одной платформе фича будет работать не так, как на другой. В-третьих, сложнее отлаживать и поддерживать.


Почему Flutter решает эти проблемы:

Flutter предлагает единую кодовую базу на Dart. Агент пишет все один раз, а не три. Токенов тратится меньше, генерация быстрее, логика не расходится.

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


🔗 Читать подробнее


💡 Вывод:

Flutter был удобен для команд, которые хотят поддерживать несколько платформ без тройного объема работы. В эпоху ИИ-агентов этот подход становится еще более актуальным. Меньше кода - меньше токенов. Одна логика - нет платформенного различия. Сильная типизация - меньше галлюцинаций. Горячая перезагрузка - быстрая проверка.

Для агентской разработки Flutter выглядит прагматичным выбором.


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик

Закрытый канал:
🚀 Мобильный трудоголик PRO
  • 👍 5
  • ❤ 3
  • 🔥 1
  • 🗿 1
Post #67 769
📱 Что делает команда git cherry-pick?

Команда git cherry-pick позволяет перенести отдельный коммит из одной ветки в другую, не сливая ветки целиком. Это полезно, когда нужно взять только конкретные изменения из другой ветки.


Как это работает:

🔵Находит коммит (по хешу) в истории Git.

🔵Применяет его изменения к текущей ветке, создавая новый коммит (с другим хешем).


Пример использования:


# Переключимся в ветку, куда нужно перенести коммит
git checkout feature

# Перенесем коммит с хешем a1b2c3
git cherry-pick a1b2c3



Вывод:

git cherry-pick – это точечный инструмент для переноса отдельных изменений. Используйте его аккуратно, чтобы не запутать историю коммитов.


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик

Закрытый канал:
🚀 Мобильный трудоголик PRO
  • ❤ 3
  • 👍 2
  • 🔥 1
  • 🙏 1
Post #66 791
👣 Expansible - новый виджет для плавно раскрывающегося списка

Во Flutter 3.32 появился новый виджет - Expansible. Он пришел на смену старому ExpansionTile и его контроллеру, который больше не поддерживается. Давайте разберем на простом примере, как он работает.


Что такое Expansible:

Expansible - это StatefulWidget, который умеет плавно раскрываться и сворачиваться. У него есть две части:

🔵header - заголовок, который всегда на виду.

🔵body - содержимое, которое появляется при раскрытии.

Анимацией управляет AnimationController, поэтому все работает плавно и без дерганий, в отличие от старого ExpansionTile.


Простой пример:

Самый частый сценарий - когда по тапу на заголовок раскрывается дополнительный контент. Вот как это выглядит:


class ExpansibleExample extends StatefulWidget {
@override
State<ExpansibleExample> createState() => _ExpansibleExampleState();
}

class _ExpansibleExampleState extends State<ExpansibleExample> {
final _controller = ExpansibleController();

@override
Widget build(BuildContext context) {
return Expansible(
controller: _controller,
headerBuilder: (context, animation) => ListTile(
title: Text('Нажми, чтобы раскрыть'),
onTap: () {
if (_controller.isExpanded) {
_controller.collapse();
} else {
_controller.expand();
}
},
trailing: RotationTransition(
turns: Tween<double>(begin: 0.0, end: 0.5).animate(animation),
child: Icon(Icons.arrow_drop_down),
),
),
bodyBuilder: (context, animation) => SizeTransition(
sizeFactor: animation,
child: Text('А вот и скрытый контент!'),
),
);
}

@override
void dispose() {
_controller.dispose();
super.dispose();
}
}


Обратите внимание на несколько важных моментов. Во-первых, ExpansibleController нужно создавать и не забывать вызывать dispose(). Во-вторых, для плавного поворота стрелочки используется animation, которая приходит в headerBuilder - она уже содержит нужное значение от 0 до 0.5 оборота. В-третьих, SizeTransition с animation анимирует высоту body. Все вместе дает аккуратный эффект без лишних телодвижений.


Важный нюанс про ListView:

Если вы используете Expansible внутри ListView или SingleChildScrollView, обязательно передавайте PageStorageKey. Иначе при скролле виджет будет терять свое состояние (раскрыт или свернут) и пользователь удивится.


Expansible(
key: PageStorageKey('unique_key_1'), // каждому Expansible свой ключ
controller: _controller,
headerBuilder: ...
bodyBuilder: ...
)



🔗 Читать подробнее


💡 Вывод:

Expansible - это не просто замена устаревшему виджету. Это инструмент, который решает давнюю боль Flutter-разработчиков: плавная анимация высоты, сохранение состояния при скролле и чистый API через контроллер. Пример выше можно скопировать и вставить в любой проект - он работает из коробки. А если нужно больше гибкости, подключайте expansibleBuilder и настраивайте под свои задачи. Если вы обновились до Flutter 3.32, присмотритесь к этому виджету - он реально удобнее.


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик

Закрытый канал:
🚀 Мобильный трудоголик PRO
  • 👍 6
  • 🔥 3
  • ❤ 1
Post #65 679
👣 Оптимизация работы анимаций во Flutter

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


AnimatedBuilder - перерисовываем только то, что нужно:

По умолчанию при каждом кадре анимации перестраивается весь виджет, который содержит AnimationController. Если внутри есть тяжелые элементы, это бьет по производительности.

AnimatedBuilder решает эту проблему. Он разделяет анимируемую часть и статический контент. Статический контент передается через параметр child и не пересоздается при каждом кадре. Перерисовывается только то, что реально меняется.


AnimatedBuilder(
animation: _animationController,
child: Container(
width: 300,
height: 300,
color: Colors.blue,
child: const Center(child: Text('Привет!')),
),
builder: (context, child) {
return Transform.rotate(
angle: _controller.value * 2 * pi,
child: child,
);
},
)



TickerMode - останавливаем анимацию, когда ее не видно:

Если пользователь свернул приложение или переключился на другой экран, а анимация продолжает работать, это пустая трата ресурсов процессора и батареи.

TickerMode позволяет отключать все анимации в определенной части дерева виджетов. Достаточно обернуть нужный участок и передать enabled: false. Все AnimationController, связанные с TickerProviderStateMixin, автоматически приостановятся.


TickerMode(
enabled: _isActive,
child: MyWidget(),
)



🔗 Читать подробнее


💡 Вывод:

AnimatedBuilder помогает не перерисовывать статику при каждом кадре, а TickerMode - не тратить ресурсы на анимацию, которую никто не видит. Вместе они делают приложение плавнее и экономичнее. Если вы используете анимации в своих проектах, эти два виджета должны быть в вашем арсенале.


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик

Закрытый канал:
🚀 Мобильный трудоголик PRO
  • 👍 5
  • 🔥 3
  • ❤ 1
Post #64 619
👣 Deeplinks во Flutter: настройка для Android и iOS

Диплинки позволяют открывать приложение по ссылке - перешел по URL и сразу попал на нужный экран. Смена пароля по ссылке из письма, открытие конкретного видео или поста, переход на карточку товара по ссылке - все это работает через deeplinks. Во Flutter нет единого решения, потому что механизм завязан на платформу. Придется настраивать Android и iOS отдельно, но это не так страшно, как кажется.

Для обработки ссылок внутри Flutter удобнее всего использовать пакет app_links. Он официально поддерживается, работает на всех платформах.


Добавляем пакет в проект:

Для добавления пакета в проект можно выполнить команду в терминале:


flutter pub add app_links


Либо добавить следующую строку в блок dependencies в файле pubspec.yaml:


app_links: ^7.1.1



Настройка для Android:

В файле android/app/src/main/AndroidManifest.xml внутри <activity> нужно добавить intent-filter. Это правило, которое говорит системе что нужно обрабатывать ссылки такого вида.


<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="your-domain.com" />
</intent-filter>


Если используете кастомную схему (не http/https), укажите ее вместо https.


App Links (https):

Для автоматического открытия ссылок в приложении нужно:

🔵Указать android:autoVerify="true" в intent-filter.

🔵Разместить файл assetlinks.json на сервере в папке .well-known (домен должен совпадать с указанным в intent-filter).

Пример файла assetlinks.json:


[
{
"relation": [
"delegate_permission/common.handle_all_urls"
],
"target": {
"namespace": "android_app",
"package_name": "com.example.yourapp",
"sha256_cert_fingerprints": [
"ваш SHA256 отпечаток"
]
}
}
]


SHA256 можно получить из Google Play Console или сгенерировать через keytool.


Настройка для iOS:

Custom scheme:

Добавьте схему в Xcode: откройте Info.plist как исходный код и добавьте:


<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>



Universal Links (https):

 Нужно:

🔵Включить Associated Domains в Capabilities проекта Xcode.

🔵Добавить applinks:your-domain.com.

🔵Разместить файл apple-app-site-association на сервере в папке .well-known.

Пример файла apple-app-site-association:


{
"applinks": {
"apps": [],
"details": [
{
"appID": "TEAMID.com.example.yourapp",
"paths": ["*"]
}
]
}
}


TEAMID можно найти в Apple Developer Account.


🔗 Читать подробнее


💡 Вывод:

Диплинки во Flutter настраиваются в несколько этапов: правим манифест на Android, добавляем entitlements на iOS, кладем файлы на сервер, а в коде используем app_links для получения ссылок и Navigator для переходов. app_links берет на себя всю сложность получения deeplink на обеих платформах. Вам остается только подписаться на поток и написать логику переходов.

После правильной настройки приложение будет корректно открываться по ссылкам из писем, мессенджеров или браузера. Главное не забыть протестировать все сценарии и убедиться, что файлы assetlinks.json и apple-app-site-association доступны по правильным адресам.


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик

Закрытый канал:
🚀 Мобильный трудоголик PRO
  • 👍 4
  • ❤ 2
  • 🙏 1
Post #63 656
👣 Причины возникновения утечек памяти и как их избежать

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


Откуда берутся утечки:

Чаще всего проблема в том, что объект создается, но не освобождается. Экран ушел, а контроллеры, подписки, таймеры или слушатели продолжают жить. Они держат ссылки на другие объекты, а те - на виджеты. В итоге память не отдается системе.


Контроллеры и dispose:

TextEditingController, ScrollController, AnimationController, FocusNode - все это нужно уничтожать в dispose(). Если этого не делать, каждый открытый экран будет оставлять после себя мусор. Правило простое: создал в initState - удали в dispose.


Подписки на Stream и слушатели:

StreamSubscription, addListener у ChangeNotifier и ValueNotifier - это классические источники утечек. Если подписался, но не отписался, поток будет слать события в уже мертвый экран. А заодно удерживать его в памяти. Решение: сохранять подписку и отменять ее в dispose.


BLoC и другие сущности с жизненным циклом:

Если BLoC создается прямо внутри State, нужно не забыть вызвать close(). Удобнее использовать BlocProvider, который сам управляет жизненным циклом. Главное правило: кто создал, тот и закрывает.


Таймеры:

Timer.periodic запускает повторяющиеся задачи. Если не отменить таймер при уходе с экрана, он будет продолжать тикать, вызывать setState и держать экран в памяти. Всегда сохраняйте ссылку на таймер и вызывайте cancel() в dispose.


Сохраненный BuildContext:

BuildContext нельзя хранить в сервисах, синглтонах или долгоживущих объектах. Он привязан к дереву виджетов. Хранив его надолго, вы случайно удерживаете в памяти целую часть интерфейса. Лучший способ - передавать контекст только в момент вызова, не сохраняя его.


Кэши без ограничений:

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


🔗 Читать подробнее


💡 Вывод:

Утечки памяти во Flutter - это не магия, а следствие забытых dispose, cancel и removeListener. Они не видны сразу, но накапливаются со временем. Самый надежный способ - профилактика: иметь чек-лист для код-ревью и периодически прогонять подозрительные сценарии через DevTools. Если относиться к dispose как к обязательной части работы с экраном, большинство проблем можно поймать еще до релиза.


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик

Закрытый канал:
🚀 Мобильный трудоголик PRO
  • ❤ 3
  • 👍 1
  • 🔥 1
Post #62 633
👣 Релиз Dart 3.12: ИИ-экосистема и синтаксические улучшения

Вместе с новой версией Flutter 3.44 команда также выпустила Dart 3.12. Обновление не самое революционное, но несколько приятных изменений в языке и экосистеме все же есть.


Приватные именованные параметры:

Раньше нельзя было написать конструктор с параметром, начинающимся на underscore. Если поле приватное, приходилось городить список инициализации:

class Bird {
final String _name;
Bird({required String name}) : _name = name;
}


Теперь можно короче:

class Bird {
final String _name;
Bird({required this._name});
}


Снаружи параметр остается публичным - underscore автоматически отбрасывается. Мелочь, но приятная.


Первичные конструкторы (эксперимент):

Одна из самых ожидаемых фич. Позволяет объявлять класс одной строкой:

class Point(final int x, final int y);


Вместо:

class Point {
final int x;
final int y;
Point(this.x, this.y);
}


Пока это экспериментальная функция, доступная с флагом --enable-experiment=primary-constructors. Если фича приживется, классы в Dart станут заметно лаконичнее.


Genkit Dart в превью:

Open-source фреймворк для создания ИИ-приложений на Dart и Flutter. С единым API для Google Gemini, Anthropic Claude и OpenAI. Можно писать логику один раз и запускать где угодно - на сервере или прямо в приложении. Плюс локальный UI для отладки промптов и трассировок.


Agentic Hot Reload:

Еще одно нововведение - горячая перезагрузка для ИИ-агентов. Через Dart MCP сервер агент сам подключается к запущенному приложению, вносит изменения и перезагружает UI. Без ручного копирования URI и настройки DTD.


🔗 Читать подробнее


💡 Вывод:

Dart 3.12 - не про революцию, а про эволюцию. Язык становится удобнее, экосистема обрастает ИИ-инструментами, а горячая перезагрузка для агентов упрощает работу с нейросетями в коде. Основные конструкторы пока экспериментальны, но их появление говорит о том, что команда думает в правильном направлении.


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик

Закрытый канал:
🚀 Мобильный трудоголик PRO
  • 👍 4
  • 🔥 2
  • ❤ 1
Post #61 582
👣 Релиз Flutter 3.44: что изменилось для разработчиков

Вышла новая версия Flutter 3.44. На первый взгляд - очередной плановый релиз. Но на самом деле это один из самых стратегически важных апдейтов за последние годы. Два главных изменения: Swift Package Manager становится стандартом для iOS/macOS, а Material и Cupertino начинают отделяться от ядра фреймворка.


Swift Package Manager вместо CocoaPods:

Долгие годы Flutter-разработчики под iOS мучились с Ruby-окружением, pod install и конфликтами версий. С выходом 3.44 SPM включен по умолчанию даже на стабильной ветке. Flutter теперь сам генерирует Swift-пакеты для Add-to-App, диагностирует несовместимые плагины и предупреждает о конфликтах между CocoaPods и SPM. CocoaPods официально уходит в историю.


Material и Cupertino отделяются от ядра:

Второе крупное изменение - библиотеки Material и Cupertino постепенно выносятся из основного SDK в отдельные пакеты material_ui и cupertino_ui. Это значит, что дизайн-системы смогут обновляться независимо от релизного цикла Flutter (раз в три месяца). В будущем приложения смогут не включать целые UI-библиотеки, если они не используются. Это шаг к модульности и уменьшению размера приложений.


Другие изменения:

🔵Infinite Carousel - бесконечная прокрутка каруселей.

🔵RoundedSuperellipseInputBorder - новые формы для полей ввода.

🔵Native desktop window showDialog - нативные диалоговые окна на десктопе.

🔵Predictive Back - улучшенные анимации возврата на Android.

🔵HCPP (Hybrid Composition++) - новая стратегия рендеринга платформенных вьюх на Android, которая решает проблемы с tearing и производительностью.

🔵Display P3 и wide gamut на macOS.

🔵Stylus support на Windows.

🔵Reduced motion на Web.

🔵Inline prediction для клавиатуры iOS.

🔵Новый flutter analyze на базе LSP.

🔵AGP 9 и Kotlin 2.x - подготовка к новым версиям Android-инструментов.

🔵Сотни фиксов Impeller, rendering pipeline и tooling.


Android - HCPP и predictive back:

HCPP - это новая стратегия для платформенных вьюх (WebView, карты). Вместо того чтобы рендерить их через offscreen-буферы, Flutter теперь делегирует композицию напрямую Android OS через Vulkan. Результат: плавный скролл, правильная обработка касаний и поддержка SurfaceView.


Web - производительность и доступность:

Flutter Web получил reduced motion support, улучшения accessibility, фиксы для Firefox, оптимизации CanvasKit и Skwasm. Генерация мусора теперь унифицирована, а шрифты загружаются быстрее.


🔗 Читать подробнее


💡 Вывод:

Flutter 3.44 закладывает фундамент, который изменит экосистему в ближайшие годы. Переход на SPM окончательно избавляет iOS-разработку от Ruby-зависимостей и делает сборку предсказуемее. HCPP и Impeller улучшают производительность на Android и iOS. А отделение Material и Cupertino от ядра открывает дорогу к легким, модульным приложениям, которые включают только нужные компоненты.


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик

Закрытый канал:
🚀 Мобильный трудоголик PRO
  • 🔥 4
  • ❤ 2
  • 👍 1
Post #60 765
👣 yx_navigation: декларативная навигация во Flutter

Привет! Наткнулся на интересную статью, где разработчики из Яндекса рассказывают, как они создали свой пакет для навигации во Flutter. Проблема знакомая: проект растет, появляются табы, вложенные модули, диплинки, а стандартные решения перестают работать. В итоге они написали свое решение и поделились им со всеми.


В чем суть:

Основная идея yx_navigation в том, что состояние навигации - это не стек, а дерево узлов RouteNode. Каждый узел содержит маршрут, параметры и список дочерних узлов. Все просто: добавил узел - экран появился, убрал - исчез.


Какую проблему решает:

🔵Мутация неактивных ветвей. Ключевая фича. Пользователь во вкладке «Сообщения», а в это время прилетает заказ. Его нужно добавить во вкладку «Заказы», но без переключения на нее. В go_router это невозможно - любой переход переключает вкладку. В yx_navigation можно получить контроллер, привязанный к неактивной ветке, и выполнить push из бизнес-логики.

🔵Управление навигацией без BuildContext. Большинство пакетов требуют context для переходов. Интерактор, обрабатывающий push-уведомление, контекста не имеет. В yx_navigation можно создать менеджер состояния заранее и управлять навигацией откуда угодно.

🔵Изоляция фич. Фича подключается одной строкой. Хост не знает о внутренних маршрутах фичи, фича - о хосте. Команды могут работать независимо.

🔵Совместимость с легаси-кодом. Старый код на Navigator.push(), showDialog() продолжает работать. Compatibility Layer адаптирует вызовы к новой модели.

🔵Дружелюбие к разработчику. Встроенная debug-панель показывает дерево состояния в реальном времени, историю мутаций и сериализованное состояние в URL.


🔗 Читать подробнее


💡 Вывод:

yx_navigation - не очередная обертка над Navigator 2.0, а решение, выросшее из реальных проблем крупного проекта. Пакет подойдет тем, кто уперся в ограничения go_router, кому надоело ждать кодогенерацию в auto_route и кто хочет управлять навигацией без привязки к UI и менять состояние даже в неактивных вкладках.


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик

Закрытый канал:
🚀 Мобильный трудоголик PRO
  • ❤ 4
  • 🔥 2
  • 👍 1
Post #59 891
👣 Agent Skills для Flutter и Dart: готовые инструкции для типовых задач

Команда Flutter представила Agent Skills - специальные инструкции, которые делают ИИ-ассистентов более компетентными в разработке на Flutter и Dart. Это не просто документация, а готовые сценарии для типовых задач: локализация, адаптивная верстка, интеграционные тесты, использование новых возможностей языка.


Зачем это нужно:

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

Важное отличие от MCP: Model Context Protocol дает агентам инструменты (молоток и гвозди), а Skills учат, как этими инструментами пользоваться (чертеж и навыки строителя). Skills также экономят токены благодаря «прогрессивному раскрытию» - агент подгружает инструкции только тогда, когда они действительно нужны.


От теории к практике:

Ранние эксперименты показали: Skills, которые просто дают документацию, не так полезны. Документация Flutter и так открыта и современные модели неплохо умеют находить нужную информацию. Поэтому команда сделала Skills задаче-ориентированными - они учат агента выполнять конкретные действия.


Что уже доступно:

Примеры Skills из открытых репозиториев:

🔵flutter-add-integration-test - настраивает Flutter Driver и превращает MCP-действия в постоянные интеграционные тесты.

🔵flutter-setup-localization - добавляет поддержку локализации в проект.

🔵flutter-build-responsive-layout - создает адаптивный макет через LayoutBuilder, MediaQuery или Expanded/Flexible.

🔵dart-use-pattern-matching - рефакторит код с использованием pattern matching из Dart.

🔵dart-collect-coverage - собирает покрытие тестами и генерирует LCOV-отчет.


🔗 Читать подробнее


💡 Вывод:

Agent Skills - шаг к тому, чтобы ИИ-ассистенты перестали быть просто умными поисковиками и стали реальными помощниками в конкретных задачах. Пока доступен базовый набор, но команда обещает расширять его вместе с сообществом. Agent Skills не превратят ИИ в сеньора, но избавят от необходимости каждый раз объяснять, как настроить локализацию или собрать покрытие тестами.


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик

Закрытый канал:
🚀 Мобильный трудоголик PRO
  • ❤ 5
  • 🔥 2
  • 🙏 1
Post #58 2.02K
👣 Flutter отказывается от CocoaPods в пользу Swift Package Manager

Начиная с релиза Flutter 3.44, Swift Package Manager (SPM) заменяет CocoaPods как стандартный менеджер зависимостей для iOS и macOS. Это означает, что больше не нужно возиться с установкой Ruby или настройкой CocoaPods, чтобы просто запустить приложение.


Почему CocoaPods уходит:

CocoaPods официально переведен в режим поддержки без активного развития. Его реестр станет доступен только для чтения 2 декабря 2026 года. Существующие сборки продолжат работать, но новые версии пакетов добавляться уже не будут. Flutter переходит на решение, которое официально поддерживает Apple, чтобы приложения продолжали получать обновления зависимостей и имели доступ к экосистеме Swift-пакетов.


Что будет с приложениями:

Flutter CLI автоматизирует переход. При сборке или запуске iOS / macOS приложения CLI сам обновит Xcode-проект для использования SPM. Если приложение использует плагины, которые еще не перешли на SPM, Flutter выдаст предупреждение и временно использует CocoaPods для таких плагинов.

В случае критических проблем можно временно отключить SPM в pubspec.yaml:

flutter:
config:
enable-swift-package-manager: false


Но компания просит сообщать о таких проблемах, чтобы успеть их исправить до полного удаления CocoaPods.


🔗 Читать подробнее


💡 Вывод:

Переход на SPM - неизбежный шаг. CocoaPods устарел, и поддержка его заканчивается. Для разработчиков приложений процесс в основном автоматический. А вот авторам плагинов предстоит работа - иначе их пакеты станут несовместимыми и потеряют позиции на pub.dev. Лучше заняться этим сейчас, а не ждать, когда CocoaPods окончательно отключат.


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик

Закрытый канал:
🚀 Мобильный трудоголик PRO
  • 👍 5
  • 🔥 2
  • ❤ 1
Post #57 909
👣 Улучшаем локальный поиск на Dart и Flutter

Обычный строковый поиск работает только при точном совпадении. Одна лишняя буква, опечатка или другой падеж и результат пустой. В этой статье автор разбирает, как реализовать локальный поиск, который понимает, что пользователь имел в виду, даже если ввел с ошибкой.


Почему простое вхождение не работает:

Пользователи часто ошибаются. Вместо «Арбатская» пишут «Орбатская», вместо «Петровка» - «Питровка». Простой поиск по вхождению подстроки такие запросы игнорирует. А отправлять каждый запрос на сервер - долго и не всегда возможно.


Что такое расстояние Левенштейна:

Это число, которое показывает, сколько операций нужно, чтобы превратить одну строку в другую. Операции - вставка, удаление, замена символа. Например, «кот» -> «код»: одна замена символа, расстояние = 1. «Австрия» -> «Австралия»: нужно добавить две буквы, расстояние = 2.

Для поиска удобнее использовать нормализованное значение от 0 до 1, где 0 - полное совпадение, 1 - строки разные.


Более точный вариант - расстояние Дамерау‑Левенштейна:

Оно добавляет еще одну операцию - перестановку соседних символов. Это одна из самых частых опечаток: «годки» вместо «годик». Обычное расстояние Левенштейна даст 2, а расстояние Дамерау‑Левенштейна - 1, потому что достаточно переставить буквы.


Как это реализовать во Flutter:

Автор приводит пример поиска по адресам и станциям метро. Алгоритм:

🔵Привести строки к нижнему регистру.

🔵Вычислить расстояние Дамерау‑Левенштейна между поисковым запросом и каждым элементом списка.

🔵Добавить к адресу название метро, если оно есть.

🔵Отсортировать результаты по близости (чем меньше расстояние, тем выше результат).

🔵Отфильтровать только те, где расстояние меньше заданного порога (например, 0.5).


🔗 Читать подробнее


💡 Вывод:

Такой поиск имеет смысл не везде. В идеале - отдать поиск на бэкенд, если он это умеет. Если нет и приходится искать локально, расстояние Дамерау-Левенштейна может спасти ситуацию. Но не ждите чудес: алгоритм требовательный к ресурсам, а порог совпадения придется подбирать вручную.


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик

Закрытый канал:
🚀 Мобильный трудоголик PRO
  • 👍 4
  • ❤ 1
  • 🔥 1
Post #56 922
👣 Как создать свое расширение для Dart DevTools

Привет! Наткнулся на статью, где автор подробно рассказывает, как добавить собственную вкладку в Dart DevTools и настроить взаимодействие с запущенным Flutter-приложением. Оказывается, это не так сложно, как кажется.


С чего начать:

Первым делом создается новый пакет под расширение. Официального шаблона нет, поэтому структуру добавляют вручную. В корне пакета создается папка devtools, внутри - build и файл конфигурации config.yaml. В конфиге указываются имя, версия, иконка для вкладки и трекер ошибок:

Файл config.yaml:

name: my_dev_tools_ext
issueTracker: https://...
version: 0.0.1
materialIconCodePoint: '0xe0b1'
requiresConnection: false


Для работы расширения нужен пакет devtools_extensions. Он дает доступ к менеджерам: extensionManager (взаимодействие с DevTools), serviceManager (доступ к VM-сервису) и dtdManager (связь с Dart Tooling Daemon).


Интерфейс и тестирование:

Сами виджеты можно собирать из готовых компонентов пакета devtools_app_shared. Например DevToolsButton уже имеет стиль, подходящий для интерфейса DevTools, а через extensionManager.showNotification можно показывать уведомления.

Для отладки расширения используется симулированная среда:

flutter run -d chrome --dart-define=use_simulated_environment=true


Перед публикацией сборка создается командой build_and_copy, а проверить корректность структуры можно через validate.


Два типа расширений:

🔵Standalone extensions - отдельные пакеты, не привязанные к существующему pub-пакету. Подходят для инструментов, которые могут пригодиться в любом проекте.

🔵Companion extensions - поставляются вместе с существующим pub-пакетом. Когда пользователь подключает такой пакет, расширение автоматически появляется в DevTools. Для этого в корне пакета достаточно добавить папку extension/devtools со сборкой и конфигом.


🔗 Читать подробнее


💡 Вывод:

Расширения DevTools открывают интересные возможности для создания инструментов отладки, визуализации состояния и даже управления приложением в рантайме. Статья дает хороший практический старт: от создания пакета до выполнения произвольного Dart-кода на живом приложении. Если вы когда-нибудь хотели добавить свою вкладку в DevTools - это вполне реально.


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик

Закрытый канал:
🚀 Мобильный трудоголик PRO
  • 👍 3
  • ❤ 2
  • 🙏 1
Post #55 2.27K
👣 Два года спустя: как увольнения повлияли на Flutter

Всем привет! Сегодня хочу разобрать интересную статью про судьбу Flutter после увольнений в Google. В апреле 2024 года Google уволил инженеров из команд Flutter, Dart и Python - за несколько недель до Google I/O, где традиционно анонсировали светлое будущее. Тогда было много паники и постов «Flutter умер». Прошло два года. Flutter не умер. Но и не остался прежним. Пора без истерик разобраться, что на самом деле изменилось.


Что тогда произошло:

Увольнения затронули в основном DevOps и инфраструктуру, а не разработчиков самого фреймворка. План развития продукта не изменился. Но сообщество правильно прочитало сигнал: для Google Flutter - больше не стратегический приоритет, а просто поддерживаемый продукт. Разница огромная. Стратегическому приоритету выделяют лучших инженеров, лоббируют внутри компании, вкладывают ресурсы. Поддерживаемому продукту - фиксят критические баги, но новых горизонтов не открывают.


Что случилось потом:

Flutter продолжил выпускать релизы. Impeller стал стабильным. Дорожная карта 2024 года выполнена. BMW, Alibaba и eBay все еще используют Flutter на проде. Опрос Stack Overflow 2024 показал 46% использования среди кроссплатформенных фреймворков - больше, чем у React Native (35%).

Но вот что важно: Тим Снит (многолетний руководитель разработки Flutter, лицо проекта на I/O) ушел в Apple в 2023 году. Брэндон ДеРозье (создатель Impeller) в 2025 году перешел в команду Android XR. Это не увольнения. Это добровольные уходы ключевых людей. И они сигнализируют о том, что даже внутри Google самые талантливые инженеры перестали видеть будущее за Flutter.


Почему я все еще использую Flutter:

Фреймворк работает. Для 90% задач кроссплатформенной разработки - стабильно, быстро, предсказуемо. Сообщество огромное, уже более 50 000 пакетов на pub.dev. Релизы выходят четыре раза в год. С точки зрения инженерной реальности Flutter не стал хуже.

Но соотношение затрат и выгод изменилось. Теперь нужно задавать себе другие вопросы.


🔗 Читать подробнее


💡 Вывод:

Используйте Flutter там, где он подходит. Понимайте свои зависимости и риски. Не принимайте архитектурные решения по звездам на GitHub и по рекомендациям от ИИ. Релевантный показатель один: решает ли фреймворк вашу проблему сегодня и есть ли у него разумный путь поддержки на три года вперед. По этому показателю Flutter проходит проверку. Не на отлично. Не так уверенно, как в 2021 году. Но проходит. Те, кто ожидает немедленного краха, ошибаются. Те, кто утверждает, что все осталось по-прежнему, тоже ошибаются. Правда, как обычно, посередине: Flutter - рабочий инструмент, но теперь его стоит выбирать с открытыми глазами, понимая, что уровень поддержки со стороны Google может и дальше снижаться.


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик

Закрытый канал:
🚀 Мобильный трудоголик PRO
  • ❤ 3
  • 👍 1
  • 👀 1
Post #54 1.01K
👣 Команда Flutter отправляется в тур по конференциям: список ивентов на 2026

Команда объявила о своем участии в десятках конференций по всему миру в 2026 году. Цель - не просто показать доклады, а лично пообщаться с разработчиками, увидеть демо вживую и собрать обратную связь. Это хорошая возможность для всех, кто давно хотел задать вопрос команде или поделиться своим мнением.


Где и когда:

В апреле стартует Google Cloud Next в Лас-Вегасе. В мае - Flutterconf в Испании, Google I/O в Саннивейле и Flutter Flow Developers Conference в Сан-Франциско. Летом команда будет в Праге, Варшаве, Берлине, Бангалоре и Орландо. Осенью - в Стокгольме, Канкуне, Берлине, Токио и других городах. Полный список обновляется на странице событий Flutter.dev.


Если вы не можете приехать - не проблема:

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


Почему это важно:

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

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


🔗 Читать подробнее


💡 Вывод:

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


Подписаться на канал:
➡️ Flutter & Dart | Мобильный трудоголик

Закрытый канал:
🚀 Мобильный трудоголик PRO
  • 👍 4
  • ❤ 1
  • 🗿 1
Post #53 1.05K
👣 Команда Flutter перевела свои сайты на Jaspr - фреймворк на Dart

Команда Flutter объявила о миграции трех основных своих сайтов (dart.dev, flutter.dev и docs.flutter.dev) на Jaspr - open-source фреймворк для создания веб-сайтов на Dart. Раньше сайты были собраны из разных технологий: документация работала на Eleventy (Node.js), а основной сайт - на Wagtail (Python + Django). Теперь все на Dart.


Почему они решили это сделать:

Старая архитектура была фрагментированной. Чтобы вносить правки или поддерживать сайты, нужно было знать Node.js, Python и Dart одновременно. Это создавало барьер для контрибьюторов и усложняло поддержку. Кроме того, добавление интерактивных элементов (например, викторин в туториалах) требовало сложных, разовых решений.


Что изменилось:

Теперь все три сайта используют единый стек на Dart. Основные изменения:

🔵Единая тулчейн. Все управляется через dart pub, dart format, dart analyze, dart test. Не нужно переключаться между разными экосистемами.

🔵Порог входа снизился. Если вы знаете Dart, вы можете вносить вклад в документацию Flutter. Никакого дополнительного обучения.

🔵Частичная гидратация. Jaspr умеет рендерить страницы как статический HTML, а потом подключать клиентскую логику только для тех компонентов, которым это нужно. Это дает быструю загрузку и хорошее SEO.

🔵Контент остался в Markdown. Рабочие процессы авторов почти не изменились. Jaspr Content поддерживает Markdown из коробки.


Почему так лучше:

🔵Flutter-разработчики чувствуют себя как дома. Компоненты Jaspr напоминают Flutter-виджеты, синтаксис похож.

🔵Современный Dart. Используются последние фичи языка: точечные шорткаты, null-aware элементы, свежие возможности JS-интеропа.

🔵Легко добавлять интерактив. Встроенная поддержка частичной гидратации позволяет без боли внедрять динамические элементы на статический сайт.

🔵Плагин анализатора. Jaspr предоставляет линтер и автодополнения прямо в IDE, как у Flutter.


🔗 Читать подробнее


💡 Вывод:

Миграция на Jaspr - пример того, как сообщество и официальная команда совместно улучшают экосистему. Единый стек на Dart упрощает поддержку, снижает порог входа для контрибьюторов и открывает возможности для более интерактивной документации. Если вы когда-нибудь хотели попробовать веб-разработку на Dart - теперь есть отличный повод.


➡️ Flutter & Dart | Мобильный трудоголик
  • 👍 4
  • ❤ 2
Post #52 933
👣 Flutter: выносим бизнес-логику из BLoC в use-cases

При разработке Flutter-приложений паттерн BLoC часто становится всемогущим объектом, впитывающим всю бизнес-логику. Внутри хендлеров оказываются и запросы к сервисам, и валидация и эмиттеры состояния. Проект разрастается, файлы раздуваются, тестирование становится невозможным. Сегодня обсудим как можно вынести бизнес-логику в отдельные классы - use-cases.


Как это работает:

Вместо того чтобы вызывать сервисы прямо внутри хендлеров BLoC, вся логика конкретного сценария (например загрузки товаров) выносится в отдельный класс. Use-case зависит от абстракций репозиториев и сервисов, но ничего не знает про UI. Он вызывает нужные зависимости, обрабатывает ошибки, выполняет side-эффекты и только после этого отправляет событие в BLoC. Сам BLoC превращается в тонкую прослойку: принимает события, обновляет состояние и больше ничего не делает.

Как это работает на практике:

Огромный BLoC-файл, отвечающий за получение данных, кэширование, фильтрацию и обновление UI, превращается в узкое место проекта. Конструктор забит зависимостями, тестирование почти невозможно. После рефакторинга BLoC сокращается до 20-30 строк, не зависит от сервисов и становится просто набором функций для обновления состояния. Все пользовательские сценарии выносятся в отдельные use-cases.

В результате время разработки нового функционала сокращается, количество багов снижается, тесты становятся надежнее.


Почему это работает:

Use-case оркестрирует несколько сервисов и репозиториев, объединяет данные, обрабатывает ошибки, логирует и только после этого отправляет событие в BLoC. BLoC остается только стейт-менеджером и не выполняет ничего, кроме преобразования событий в состояние. Такой подход соответствует принципам чистой архитектуры: доменный слой не зависит от реализации, что повышает гибкость и тестируемость.


🔗 Читать подробнее


💡 Вывод:

Разделение бизнес-логики и UI - необходимость для масштабируемых приложений. Use-cases помогают структурировать код, упрощают тестирование и делают BLoC максимально простым. Этот подход не привязан к BLoC и может использоваться с любым другим стейт-менеджером.


➡️ Flutter & Dart | Мобильный трудоголик
  • 🔥 5
  • ❤ 1
  • 👍 1
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →