Flutter & Dart | Мобильный трудоголик
167 subscribers
15 photos
1 video
47 links
Пишу простым языком про разработку на Flutter & Dart (iOS, Android, macOS, Windows) и мобильную разработку в целом.
Обо мне: https://xn--r1a.website/hardworkerFlutter/2
Чат: @flutterDevChat
Другие мои каналы: @hardworkerIT и @itDenisov
Download Telegram
👣 Обновлен плагин Flutter для VS Code: что нового?

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


Тесты теперь работают адекватно:

В этом обновлении тестам уделили особое внимание. Исправили несколько раздражающих багов: тесты больше не выдают ошибку Cannot read properties of null в консоли, не пропадают из панели результатов и не помечаются ошибочно как пропущенные.

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

Для тех, кто использует test_reflective_loader, тесты теперь группируются по классам - навигация по результатам становится чище.


Параллельные действия:

Команда Get Packages for All Projects теперь умеет запускать несколько процессов одновременно. Раньше пакеты подтягивались последовательно для каждого проекта, что могло затягиваться. Теперь все летает параллельно, используя до половины ядер процессора.


Редактор и навигация:

Несколько мелочей, которые важны в ежедневной работе:

🔵Переход к импорту больше не прыгает в другую вкладку, если файл уже открыт - остается там, где удобно.

🔵Исправления для зависимостей теперь корректно перемещают их из dev_dependencies в dependencies, если это нужно.

🔵Подсветка ключевых слов стала единообразной - разница между начальной и семантической подсветкой ушла.

🔵Обновили грамматику для грядущих Primary Constructors - готовимся к новым фичам Dart.

🔵Геттеры и поля теперь отображаются точнее, без путаницы.


Работа с эмуляторами:

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


Совместимость и старые версии:

Поддержка SDK ниже Dart 3.2 / Flutter 3.16 окончательно прекращена. Если вы все еще сидите на древних версиях, придется либо обновляться, либо откатывать плагин до старой версии - на сайте есть таблица совместимости.


Что будет в будущих SDK:

Некоторые фичи уже есть в бета-версиях, но в стабильных появятся позже:

🔵Стек-трейсы теперь показываются в всплывающих окнах, даже если ошибка проброшена через Completer.completeError().

🔵Фабричные конструкторы больше не отображаются как <unknown> в навигации.


🔗 Ссылка на плагин


💡 Вывод:

Очередное обновление, которое не кричит о себе, но делает работу с Flutter в VS Code чуть более предсказуемой и быстрой. Особенно радуют правки тестов и параллельные операции. Если вы активно используете VS Code для разработки - обновляйтесь, мелочи действительно имеют значение.


➡️ Flutter & Dart | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍41
👣 Анонсирован Genkit для Dart: фреймворк для ИИ-приложений

Google анонсировала Genkit Dart - open-source фреймворк для создания полноценных ИИ-приложений на Dart и Flutter. Это не просто очередная обертка над API, а инструмент, который позволяет строить сложные ИИ-сценарии с типизацией, тестированием и удобным UI для отладки. Пока в предварительной версии, но уже выглядит многообещающе.


Что такое Genkit Dart и зачем он нужен:

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

🔵Единый API для работы с разными моделями (Google Gemini, OpenAI, Anthropic и другие совместимые).

🔵Строгая типизация ответов - никаких неожиданных форматов.

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

🔵Удобный локальный UI для тестирования и отладки промптов.


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

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


Все внутри Flutter (для прототипов):

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


Бэкенд + Flutter с общей типизацией:

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


Прокси-сервер для моделей:

Компромиссный вариант: на сервере поднимается тонкая прослойка, которая проксирует запросы к ИИ-моделям, добавляя авторизацию и валидацию. Ключи API хранятся на сервере, а Flutter-приложение общается с ним как с обычным Genkit-клиентом.


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


💡 Вывод:

Genkit Dart - это попытка внести порядок в хаос ИИ-разработки. Вместо того чтобы каждый раз городить свои обертки над моделями, можно взять готовый фреймворк с типизацией, тестируемостью и удобным UI. Пока это превью, но направление выглядит правильным. Если вы работаете с Dart/Flutter и думаете, как добавить в проект ИИ-фичи - присмотритесь.


➡️ Flutter & Dart | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4👍1
This media is not supported in your browser
VIEW IN TELEGRAM
👣 Как добавить эффект Liquid Glass в Flutter-приложение

С выходом iOS 26 компания Apple представила дизайн Liquid Glass - ту самую жидкую стеклянную эстетику, которая делает интерфейсы объемными и тактильно приятными. Сообщество Flutter все это время искало способ повторить это на своей платформе. Попытки были, но с ограничениями: кто-то завязывался на Impeller и терял поддержку Windows и Web, кто-то просто делал обычное размытие, выдавая его за жидкое стекло. Теперь появилось работающее кроссплатформенное решение.


Что раньше:

Краткий обзор того, что предлагалось раньше:

🔵Пакеты, которые либо не работали, либо не имели примеров.

🔵Решения, завязанные на Impeller - красиво, но только для мобилок.

🔵Обычный стекломорфизм с размытием, который никакой не жидкий.

🔵Нативные обертки, которые работали только на iOS.

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


Что появилось сейчас:

Пакет liquid_glass_easy делает именно то, что заявлено: настоящие интерактивные линзы из жидкого стекла с физикой преломления, искажения и реакции на касания. Работает на Android, iOS, Web, macOS и Windows. В основе - GPU-шейдеры, так что производительность остается высокой даже при нескольких активных линзах.


Как это устроено:

Все строится вокруг двух виджетов:

🔵LiquidGlassView - контейнер, который захватывает содержимое фона в реальном времени и передает его в линзы.

🔵LiquidGlass - сама линза, которую можно настроить: форма, размер, степень искажения, размытие, цвет, направление света.

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


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


💡 Вывод:

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


➡️ Flutter & Dart | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥41👍1
👣 Keys во Flutter: как не потерять состояние при перестройке списков

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


Для чего используются Keys:

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

Keys дают Flutter дополнительную информацию: вместо «третий элемент в списке» он ищет «элемент с таким-то идентификатором». Благодаря этому состояние прикрепляется к конкретному объекту, а не к индексу.


Типы ключей и когда их выбирать:

🔵ValueKey - самый частый выбор. Берет какое-то стабильное значение (id, уникальный заголовок) и использует его как идентификатор. Идеально для списков, где у каждого элемента есть уникальный ключ из данных.

🔵ObjectKey - использует сам объект в качестве идентификатора, сравнивая его через стандартный оператор ==. Пригождается, когда у элемента нет уникального поля (например id), но сам объект достаточно стабилен и не меняется в процессе работы.

🔵UniqueKey - каждый раз создает новый идентификатор. Это гарантирует, что Flutter не будет пытаться сопоставить виджет с предыдущим, а создаст новый элемент с нуля. Удобно, когда нужно принудительно сбросить состояние (например пересоздать анимацию), но использовать на каждый чих не стоит - производительность пострадает.

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


Где без ключей не обойтись:

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

🔵Виджеты, которые меняют порядок в зависимости от условий.

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


Где ключи не нужны:

🔵Статичные списки, которые не меняются.

🔵Виджеты без внутреннего состояния (статусные иконки, просто текст).

🔵Случаи, где состояние вообще не важно.


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

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


💡 Вывод:

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


➡️ Flutter & Dart | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31
👣 Flutter и нативный код: как работают MethodChannel и EventChannel

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


Как устроен этот мост:

Все взаимодействие строится вокруг каналов. Это не магия, а просто способ передавать сообщения туда и обратно. Dart-код отправляет запрос, нативная сторона его обрабатывает и возвращает ответ. Все данные при этом сериализуются (превращаются в понятный для обеих сторон формат) и десериализуются обратно.

Самый частый сценарий - метод-канал (MethodChannel). Это как вызов функции, но на удаленной стороне. Вызываете метод с именем, передаете параметры, ждете ответа. Все асинхронно, то есть приложение не зависает, пока нативная часть думает.


Когда нужен MethodChannel:

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

В нативной части (Android на Kotlin, iOS на Swift) этот же канал регистрируется, и для каждого вызова прописывается обработчик. Если метод известен - возвращается результат, если нет - вызывается notImplemented.


Когда нужен EventChannel:

Бывают ситуации, когда данные приходят не по запросу, а сами. Например, акселерометр или датчик движения - они отправляют показатели постоянно, пока подписка активна. Здесь пригождается EventChannel.

Flutter подписывается на поток, нативная сторона начинает слать события через специальный объект (eventSink). Как только подписка отменяется, поток закрывается. Это идеально для датчиков, геолокации, состояния батареи - всего, что меняется во времени.


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


💡 Вывод:

Платформенные каналы - это не страшно. MethodChannel закрывает задачи «спросили - получили», EventChannel - «подписались - получаем поток». Главное - помнить про асинхронность, типы данных и не перегружать главный поток. Если нужна сложная логика, лучше вынести ее в нативную часть, а в Dart только вызывать и получать результат. А еще - всегда оборачивать вызовы в try-catch, потому что нативная сторона может вернуть ошибку.


➡️ Flutter & Dart | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥21
🏋️ Установка APK на Android усложняется: придется ждать сутки

С августа 2026 года установка APK-файлов от неизвестных разработчиков на Android станет сложнее. Google вводит продвинутый процесс, который должен защитить пользователей от мошенников, но заодно превращает установку любого приложения не из Google Play в квест.

Это касается не только нативных разработчиков, но и разработчиков на Flutter, которые собирают приложения под Android и которые распространяют свои приложения в обход Google Play (например через сайты, соц. сети или телеграм). Это означает, что привычный способ «включил неизвестные источники -> установил» больше не сработает. Вместо этого - сутки ожидания, биометрия и подтверждение, что вас никто не принуждает.


Что изменится:

Раньше достаточно было включить разрешение на установку из неизвестных источников и можно было ставить любой APK. Теперь нужно будет пройти целую процедуру:

🔵Включить режим разработчика.

🔵Подтвердить, что вас никто не принуждает.

🔵Перезагрузить телефон.

🔵Подождать сутки.

🔵Пройти биометрическую проверку.

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


Почему ввели данный процесс:

Google объясняет это борьбой с мошенниками. По статистике Global Anti-Scam Alliance, 57% взрослых сталкивались с мошенничеством за последний год, а ущерб составил 442 миллиарда долларов. Мошенники часто давят на жертв по телефону, заставляя прямо сейчас отключить защиту и установить вредоносное приложение. Принудительная пауза в сутки должна сломать эту схему.

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


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


💡 Вывод:

Android теряет одну из главных своих особенностей - свободу установки любого приложения без ограничений. Теперь это будет возможно только после процедуры с суточным ожиданием. Google говорит о безопасности и это действительно важная тема. Для нативных разработчиков и Flutter-разработчиков, которые тестируют сборки на реальных устройствах, раздают бета-версии клиентам через телеграм или просто устанавливают собственные APK в процессе разработки, это ощущается как шаг назад. В погоне за защитой от мошенников страдают в том числе разработчики, которым нужна возможность быстро ставить приложения не из магазина.


➡️ Flutter & Dart | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👀4🙏2👍1🗿1
👣 Когда в Dart нужен covariant и как он работает

В Dart есть ключевое слово covariant, о котором многие слышали, но используют редко. А зря, оно решает конкретную проблему с переопределением методов в наследниках, когда нужно уточнить тип параметра. Разбираемся, как это работает и в каких случаях пригождается.


В чем суть проблемы:

Представьте, что у вас есть базовый класс Employee с методом process, который принимает любой тип документа (Document). Вы создаете наследника Manager, который по логике должен работать только с отчетами (Report), а не с любыми документами.

По умолчанию Dart этого не позволит. Метод в наследнике должен принимать тот же тип, что и в родителе - Document. Если вы попытаетесь сузить тип до Report, компилятор выдаст ошибку.



class Employee {
void process(Document doc) {}
}

class Manager extends Employee {
@override
void process(Report doc) {} // ошибка переопределения
}



Что делает covariant:

Ключевое слово covariant говорит компилятору: «Этот параметр может быть сужен в наследниках». Добавляем его в базовый класс и все работает:


class Employee {
void process(covariant Document doc) {}
}

class Manager extends Employee {
@override
void process(Report doc) {} // теперь можно
}


Теперь метод process у Manager принимает только Report. Попытка передать Invoice вызовет ошибку типов.


Когда это полезно:

Ситуации, когда нужно уточнить тип параметра в наследнике, возникают не так часто, но бывают. Например:

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

🔵В фабриках и билдерах, где базовый метод принимает общий тип, а наследники работают с конкретными объектами.

Без covariant пришлось бы делать приведение типов внутри метода или проверять тип вручную. С ним код становится чище и типобезопаснее.


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


💡 Вывод:

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


➡️ Flutter & Dart | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥21
👣 Что важно знать о BuildContext в Flutter

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


Как на самом деле работает поиск:

Когда вы вызываете Theme.of(context), Flutter начинает подниматься вверх по дереву от текущего контекста, пока не найдет ближайшего предка нужного типа. Если у вас вложенные темы, context определяет, какую из них вы получите.

Отсюда и берутся проблемы: Navigator.of(context) иногда не работает, потому что контекст находится выше того навигатора, который вы пытаетесь использовать. Или Scaffold.of(context) не видит Scaffold, потому что context создан раньше.


Где чаще всего спотыкаются:

🔵initState - запретная зона. Нельзя использовать context напрямую в initState. Если нужно что-то показать при открытии экрана, приходится использовать addPostFrameCallback. Иначе приложение упадет.

🔵Асинхронные операции - ловушка. Вы сделали запрос, ждали ответа, а пользователь уже закрыл экран. Если попробовать использовать старый context будет краш. Поэтому после каждого await нужно проверять if (!context.mounted) return;

🔵Диалоги - отдельная история. Чтобы закрыть диалог изнутри, нужно использовать контекст, который приходит в builder, а не тот, что был снаружи. Иначе навигатор не поймет, что именно закрывать.


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


💡 Вывод:

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


➡️ Flutter & Dart | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32🔥1
👣 DataTable и Table: работа с таблицами во Flutter

В повседневной работе мы привыкли к Column, Row, ListView. Они закрывают большинство задач по построению интерфейсов. Но иногда требуется настоящая таблица: строки, столбцы, сортировка, постраничная навигация. И здесь у Flutter есть несколько специализированных инструментов, о которых многие забывают.


DataTable - для небольших объемов:

Если у вас предсказуемый, небольшой набор данных - идеальный вариант. DataTable строится на основе DataRow и DataCell, все объявляется декларативно. Подходит для экранов настроек, административных панелей, любых мест, где таблица не превышает десятка строк. Сортировка подключается через onSort, постраничное отображение контента - через PaginatedDataTable, которая оборачивает обычную DataTable и добавляет навигацию.


Table - полный контроль:

Если нужно управлять каждой ячейкой, задавать разную ширину колонок, рисовать границы, вставлять сложные виджеты - используйте Table. Здесь вы сами определяете каждую строку как TableRow, а внутри - список ячеек с любыми виджетами. Можно задавать ширину колонок: фиксированную (FixedColumnWidth), пропорциональную (FlexColumnWidth) или по содержимому (IntrinsicColumnWidth).


Что важно знать:

🔵IntrinsicColumnWidth - заставляет Flutter делать два прохода: сначала измерить все, потом отрисовать. На сотнях строк это может начать тормозить.

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

🔵Динамическая высота строк - если содержимое ячеек часто меняется, Table может работать неоптимально. Здесь иногда проще собрать свой вариант через ListView + Row.


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


💡 Вывод:

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


➡️ Flutter & Dart | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍62🔥1
👣 Как Dart и Flutter смотрят на ИИ в 2026 году

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


Цифры, которые объясняют все:

Согласно опросам, 84% разработчиков в целом используют ИИ-инструменты в своей работе. Среди Flutter-разработчиков этот показатель чуть ниже - 79%, но все равно впечатляет. Однако есть проблема: 46% не доверяют точности ИИ при решении критических задач. Это тратит лишнее время на проверку сгенерированного кода.


Главные принципы:

Команда декларирует несколько ключевых правил, которым следует при развитии ИИ-направления:

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

🔵Добавлять, а не заменять. ИИ-инструменты должны дополнять опыт разработки, а не вытеснять разработчика. Каждый сам решает, использовать ИИ или нет и в каком объеме. При этом документация и базовые инструменты остаются источником истины.

🔵Открытые стандарты и агентная нейтральность. Flutter должен хорошо работать с любым агентом, не только с Gemini. Для этого используются открытые протоколы вроде MCP. Например, недавно добавили MCP-инструмент для поддержки горячей перезагрузки при разработке с ИИ.

🔵Доверие через качество. Главная проблема ИИ-генерации - затраты времени на проверку. Команда работает над тем, чтобы сгенерированный код был точным, идиоматичным и соответствовал стандартам проекта. Для этого сотрудничают с Google Deepmind и Antigravity по оценке моделей.


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


💡 Вывод:

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


➡️ Flutter & Dart | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍1🙏1👀1
👣 Как удалить все неиспользуемые импорты во Flutter-проекте

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


Одна команда, которая все решает:

В корне проекта достаточно выполнить:


dart pub get && dart fix --apply


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

Если хочется сначала посмотреть, что именно будет удалено, можно выполнить dart fix --dry-run. Покажет список изменений, но ничего не тронет.


Почему об этом вообще стоит думать:

Неиспользуемые импорты не ломают код, но они делают его грязным. Ревьюеры тратят время на проверку того, что на самом деле не используется. Линтеры и форматтеры работают хуже, когда списки импортов захламлены. А сам проект со временем становится тяжелее и менее понятным.

dart fix решает эту проблему мгновенно. Инструмент официальный, встроенный в экосистему Dart, так что никаких сторонних зависимостей тащить не нужно.


Что важно помнить:

Перед массовой чисткой лучше сделать коммит - мало ли что. Сгенерированные файлы (.g.dart) dart fix трогать не должен, они все равно перезапишутся при следующей сборке. И всегда после чистки стоит прогнать dart analyze && flutter test, чтобы убедиться, что ничего не сломалось.


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


💡 Вывод:

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


➡️ Flutter & Dart | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍41
👣 Material и Cupertino больше не часть SDK Flutter

Команда Flutter объявила о заморозке изменений в библиотеках Material и Cupertino внутри основного SDK. Это первый шаг к самому масштабному архитектурному изменению в истории фреймворка - полному отделению дизайн-систем от ядра. Теперь Material и Cupertino станут обычными пакетами на pub.dev.


Какую проблему решает это изменение:

Сейчас Material и Cupertino жестко привязаны к Flutter и обновляются только с релизами SDK. Это создает несколько проблем:

🔵Зависимость от цикла релизов. Нашли баг в Material? Ждите три месяца, пока выйдет новый релиз Flutter. Нужна свежая версия Material 3? Обновляйте весь SDK, даже если вам это не нужно.

🔵Невозможность кастомизации. Сложно сделать свою дизайн-систему, чтобы из нее не торчали уши Material или Cupertino.

🔵Сложности для энтузиастов. Чтобы поправить баг в кнопке Material, нужно разбираться с локальной сборкой Flutter.

После разделения библиотеки Material и Cupertino будут обычными пакетами на pub.dev со своим версионированием и циклом обновлений.


Что будет происходить дальше:

С 7 апреля все изменения в Material и Cupertino внутри Flutter заморожены. Дальнейшая разработка продолжится в репозитории flutter/packages, где появятся новые пакеты - material_ui и cupertino_ui. После выхода стабильного релиза Flutter 3.44 новые пакеты станут доступны, и разработчикам нужно будет постепенно переходить на них.

Старые библиотеки Material и Cupertino в SDK будут объявлены устаревшими в следующем релизе после 3.44 и удалены спустя какое-то время.


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


💡 Вывод:

Flutter перестает быть фреймворком со встроенными Material и Cupertino и становится платформой, где дизайн-системы живут своей жизнью. Это не просто техническое изменение, а смена подхода: ядро SDK становится легче и стабильнее, а дизайн-системы - независимыми, с собственными циклами обновлений. Разработчики получают свободу выбора: можно использовать Material, Cupertino или свою собственную дизайн-систему. Баги теперь будут фикситься быстрее - не нужно ждать квартального релиза Flutter.


➡️ Flutter & Dart | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥2👀1
📱 Отключаем запрос о соответствии экспортным требованиям в TestFlight

Загружая новую сборку iOS-приложения, всегда приходится заходить в App Store Connect для нажатия на «Нет» в окне «Информация о соответствии экспортным требованиям».

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

Для этого необходимо открыть файл Info.plist в папке /ios/Runner и добавить следующие строки:

<key>ITSAppUsesNonExemptEncryption</key>
<false/>


Что это дает:

🔵Больше не нужно вручную отвечать «Нет» в App Store Connect.

🔵Сборки сразу становятся доступными для тестирования в TestFlight после обработки.


➡️ Flutter & Dart | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍3🔥1
👣 Оптимизация производительности приложений на Flutter

Производительность Flutter-приложения напрямую зависит от того, как написан код. Лишние перестройки UI, тяжелые операции в основном потоке, неправильная работа со списками и изображениями - все это ведет к фризам, падению FPS и раздраженным пользователям. В этом посте обсудим наиболее распространенные ошибки, которые превращают быстрый фреймворк в тормознутое приложение.


Лишние перестройки UI:

Самая частая проблема - setState, который пересобирает все дерево виджетов целиком. Даже если изменился один текст, Flutter заново вызывает build() для всех дочерних элементов. В маленьком проекте это незаметно. Когда же внутри есть списки, картинки и сложные layout'ы, каждое нажатие кнопки начинает тормозить интерфейс. Решение - использовать ValueListenableBuilderStreamBuilder или аналоги, которые обновляют только нужную часть.


Отсутствие const:

Многие забывают про const. Без него каждый rebuild создает новые объекты виджетов, даже если они идентичны предыдущим. Это увеличивает нагрузку на сборщик мусора и процессор. В больших списках или сложных UI это дает заметный прирост производительности - достаточно просто добавить const там, где это возможно.


Логика внутри build():

build() может вызываться десятки раз в секунду - при анимациях, скролле, обновлениях. Если внутри выполнять сортировку, фильтрацию или парсинг, это напрямую убивает производительность. Даже простая операция sort() на среднем списке может занимать миллисекунды, а для 60 FPS на каждый кадр есть всего 16 мс. Вся логика должна быть вынесена в initState или бизнес-слой.


ListView без builder:

Когда вы используете ListView(children: [...]), Flutter создает все элементы списка сразу, даже если пользователь видит только первые 5–10. При 100+ элементах это приводит к лишним аллокациям, перегрузке памяти и долгому первому рендеру. ListView.builder создает элементы лениво - только те, что видны на экране. Это значительно снижает нагрузку.


Отсутствие ключей:

Без key Flutter не может корректно сопоставить старые и новые элементы при обновлении списка. В результате он пересоздает виджеты вместо их обновления, что приводит к лишним rebuildам и визуальным багам - например, прыгающим элементам. ValueKey или ObjectKey решают эту проблему.


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


💡 Вывод:

Большинство проблем с производительностью возникают не из-за сложности задачи, а из-за мелких решений, которые легко упустить в процессе разработки. Лишний rebuild, тяжелая операция в основном потоке, список без builder - каждое из этих решений кажется безобидным, пока приложение не начинает тормозить. Хорошая новость в том, что большинство описанных проблем решаются относительно просто. Главное - не откладывать это на потом.


➡️ Flutter & Dart | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥21🙏1
👣 Убираем хардкод и лишние перерисовки с помощью стандартных виджетов

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


LayoutBuilder - адаптивный интерфейс без хардкода:

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

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

LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > 600) {
return Row(children: [sidebar, content]);
}
return Column(children: [sidebar, content]);
},
)



AnimatedSwitcher - плавные переходы между виджетами:

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

Важный момент: анимация сработает только если у виджетов разные key. Иначе AnimatedSwitcher решит, что ничего не изменилось.

AnimatedSwitcher(
duration: Duration(milliseconds: 300),
child: Text(counter.toString(), key: ValueKey(counter)),
)



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


💡 Вывод:

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


➡️ Flutter & Dart | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍2🙏1
👣 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 | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥51👍1
👣 Команда Flutter перевела свои сайты на Jaspr - фреймворк на Dart

Команда Flutter объявила о миграции трех основных своих сайтов (dart.devflutter.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 | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍42
👣 Команда 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 | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍41🗿1
👣 Два года спустя: как увольнения повлияли на 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 | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍1👀1
👣 Как создать свое расширение для 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 | Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32🙏1