Как стать автором
Обновить
22.91

Dart *

Язык программирования, созданный Google

Сначала показывать
Порог рейтинга

‼️ Dart отказывается от макросов! Что дальше? ‼️

Официальное объявление от команды Dart: разработка макросов остановлена.

После нескольких лет экспериментов выяснилось, что их реализация слишком сильно замедляет компиляцию и ухудшает разработческий опыт (о чем не раз писал и говорил на Crossconf 2024). У меня были предположения, что мы увидим макросы только в 2026-м году, но такого поворота событий совсем не ожидал >_<

Конечно, это не повод ставить крест на Dart, хотя и очень обидно! 😭 Вместо макросов команда сосредоточится на:

  • Улучшении работы с данными – это самая востребованная фича среди разработчиков.

  • Оптимизации build_runner – ускорение сборки и улучшение генерации кода.

  • Внедрении augmentations – новый инструмент, который упростит кодогенерацию.

👉 Подробнее об этом можно прочитать в статье на Medium, которую написал директор по разработке Dart и его экосистемы Vijay Menon

Что думаете по этому поводу? Какие в таком случае новые фичи ждете? Разочарованы ли отменой макросов?

Теги:
+1
Комментарии0

Как CodeStyle спасает Flutter-проекты от хаоса

Разрозненная структура файлов, разные подходы к оформлению и дублирование функциональности — всё это замедляет разработку и повышает вероятность ошибок.
Чтобы победить хаос, сделать работу команды быстрее и проще, попробуйте внедрить CodeStyle — это свод правил, которые делают код читаемым, стандартизированным и удобным для поддержки.

Вот что вы получите:

  • Читаемость: новые участники команды быстрее понимают проект.

  • Стандартизация: вся кодовая база выглядит так, будто ее писал один человек.

  • Поддерживаемость: проще рефакторить и находить ошибки.

Почему CodeStyle особенно важен для Flutter

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

  • разрозненной структурой файлов, которая затрудняет поиск компонентов;

  • непоследовательным оформлением кода, которое усложняет его понимание;

  • дублированием библиотек и функционала, которое приводит к путанице.

Единый CodeStyle решает эти проблемы и создает прозрачную и предсказуемую структуру проекта.

Как внедрить CodeStyle: 4 шага

1. Обучение

Проводите мастер-классы и лекции, показывайте примеры из реальных проектов. Это помогает разработчикам видеть преимущества стандартов.

2. Автоматизация

Настройте инструменты для проверки кода:

  • линтеры (например, flutter_lints) для автоматической проверки стиля;

  • pre-commit хуки (Husky или Lefthook) для форматирования кода перед коммитом.

3. Код-ревью

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

4. Командное соглашение

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

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

Теги:
0
Комментарии0

Прошедшее мероприятие от команды Flutter - #FlutterInProduction можно разбить на 3 части (если лень читать - вот ссылки на видеоразбор мероприятия ЮТУБ ВК)

👉 Разговор про эры развития Flutter:

  • эра экспериментов (2014 - 2018)

  • эра роста ( 2018 - 2022)

  • Эра кровавого энтерпрайза (начиная с середины 2022 года)

Разработчики наконец-то определились со зрелостью фреймворка и на протяжении этой части (да и всего мероприятия) нам показывали, что Flutter применяется в разных областях и крупными компаниями с огромнейшим потоком клиентов ^_^

👉 Экосистема

Тут было про поддержку различных IDE, что на pub доступны более 50к пакетов. Заострили внимание на том, что вокруг Flutter выстраивается экосистема (FlutterFlow, Shorebird, Serverpod, Codemagic), в то время как он сам по гланды интегрирован в экосистему Google☝️

Отдельно следует отметить упоминание о Flutter Consultants, что говорит о реальной зрелости фреймворка😎

👉 Если обобщить все услышанное с секцией Roadmap, получится следующая выжимка над чем будет работать команда Flutter в 2025 году:

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

🔥 Impeller (Flutter GPU) не только на мобилках, но и на десктопе (web пока под большим вопросом)

🔥🎉🥳 Средства предварительного просмотра виджетов с поддержкой редактирования

🔥🎉🥳 Прямое взаимодействие с native platform

🔥🔥🔥 Ускорение написания и упрощение чтение кода (p.s. это подгорает мой пердак от увиденных декораторов 😂, первичный конструктор - норм тема😎)

Не все показанное может быть реализовано на 100% От некоторых фич могут отказаться или перенести на потом.

А что вы думаете о прошедшем мероприятии?

Теги:
Рейтинг0
Комментарии1

Прошедшее мероприятие от команды Flutter - #FlutterInProduction можно разбить на 3 части (если лень читать - вот ссылки на видеоразбор мероприятия ЮТУБ ВК)

👉 Разговор про эры развития Flutter:

  • эра экспериментов (2014 - 2018)

  • эра роста ( 2018 - 2022)

  • Эра кровавого энтерпрайза (начиная с середины 2022 года)

Разработчики наконец-то определились со зрелостью фреймворка и на протяжении этой части (да и всего мероприятия) нам показывали, что Flutter применяется в разных областях и крупными компаниями с огромнейшим потоком клиентов ^_^

👉 Экосистема

Тут было про поддержку различных IDE, что на pub доступны более 50к пакетов. Заострили внимание на том, что вокруг Flutter выстраивается экосистема (FlutterFlow, Shorebird, Serverpod, Codemagic), в то время как он сам по гланды интегрирован в экосистему Google☝️

Отдельно следует отметить упоминание о Flutter Consultants, что говорит о реальной зрелости фреймворка😎

👉 Если обобщить все услышанное с секцией Roadmap, получится следующая выжимка над чем будет работать команда Flutter в 2025 году:

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

🔥 Impeller (Flutter GPU) не только на мобилках, но и на десктопе (web пока под большим вопросом)

🔥🎉🥳 Средства предварительного просмотра виджетов с поддержкой редактирования

🔥🎉🥳 Прямое взаимодействие с native platform

🔥🔥🔥 Ускорение написания и упрощение чтение кода (p.s. это подгорает мой пердак от увиденных декораторов 😂, первичный конструктор - норм тема😎)

Не все показанное может быть реализовано на 100% От некоторых фич могут отказаться или перенести на потом.

А что вы думаете о прошедшем мероприятии?

Теги:
Рейтинг0
Комментарии0

Hola, Amigos! Делюсь с вами записью своего доклада с конференции Mobius на тему «Создание indoor-карты здания на Flutter». Рассказал, как реализовать размещение на одном или нескольких экранах внутренней карты здания. А также раскрыл подходы и собственное решение с использованием Flutter.

Держите ссылки:

YOUTUBE 

VK

Смотрите на любой удобной платформе и делитесь в нашем чате мобильных разработчиков, на какую тему вы бы точно пришли на конференцию?

Теги:
Всего голосов 2: ↑1 и ↓1+2
Комментарии0

Hola, Amigos! На связи Павел Гершевич, Flutter Team Lead в Amiga. Сегодня поговорим про отображение HTML-тегов как виджетов в наших приложениях на Flutter.

Чаще всего для этого используется библиотека flutter_html:

Html(data: ‘<p>Hello World</p>’);

Но у нее есть несколько минусов:

– Она больше года не обновлялась, что с одной стороны хорошо, так как она стабильна, а с другой — она уже устаревает.
–В ней есть баги. Например, если внутри тега <p> окажется список (<ul>, <ol>), то снизу появляется отступ, равный высоте списка.
– Не очень понятная система стилизации. Чтобы что-то изменить, нужно разобраться, как это делается, так как вместо CSS-атрибутов используются собственные подходы.

Пример стилизации, где нужно поменять размер шрифта для всего документа:

  data: ...,
  style: {
    ‘*’: Style(
      fontSize: FontSize(15),
    ),
  }
);

Столкнувшись с этими минусами, мы решили перейти на вторую по популярности библиотеку — flutter_widget_from_html_core. Во-первых, она лишена вышеописанных багов. Во-вторых, она модульная, и к ней можно многое прикрутить.

HtmlWidget(‘<p>Hello World</p>’);

Со стилями всё интереснее. Шрифт устанавливается через стандартный TextStyle:

  ...,
  textStyle: 
TextStyle(...),
);

Но если нужно его раскрасить или что-то ещё, всё становится сложнее. Продолжение по ссылке.

Теги:
Всего голосов 3: ↑1 и ↓2+1
Комментарии0

Преимущества Rive при разработке Flutter-приложений

При разработке Flutter-приложений используют много типов анимации, о чем мы ранее уже писали. Но Rive всё-таки превосходит большинство из них. Во-первых, у него удобный встроенный UI-интерфейс. Во-вторых, в Rive есть раздел Community, где авторы выкладывают бесплатные анимации.

В-третьих, — и это главное преимущество — в Rive есть State Machine. Это визуальный способ связать анимацию воедино и определить логику, которая управляет переходами. State Machine позволяет создавать интерактивную графику движения, готовую к внедрению в ваш продукт, приложение, игру или веб-сайт.

State Machine включает несколько уровней:

  • Graph — пространство, в котором мы добавляем состояния и соединяем переходы.

  • State — анимации временной шкалы, которые могут воспроизводиться в нашей машине состояний.

  • Transaction — переходы представляют собой логическую карту для State Machine.

  • Inputs — договор между дизайнерами и разработчиками. Как дизайнеры, мы используем входы как способ управления переходами в нашей машине состояний, назначая их в качестве условий. Разработчики связываются с входами во время выполнения и определяют условия с помощью кода, который может изменить эти входы.

  • Layers — слой State Machine, который позволяет воспроизводить одну анимацию за раз.

Подробнее о том, как работает Rive и как интегрировать его в проект, в нашем блоге.

Теги:
Всего голосов 2: ↑2 и ↓0+4
Комментарии0

Главные особенности новых версий Dart и Flutter

В конце прошлой недели вышло сразу два заметных релиза: Dart 3.3 и Flutter 3.19. Объединили самое интересное в один небольшой пост.

Что нового в Dart:

Что нового во Flutter:

  • Изменения в скролле. Тут завезли оптимизацию и гибкость в управление поведением.

  • Виджет AnimationStyle. Он позволяет юзерам менять стандартное поведение анимации в виджетах. А разработчики с его помощью могут переопределять кривые и продолжительность анимации.

  • Adaptive Switch. Компонент выглядит и ведет себя как нативный на macOS и iOS, а в других случаях — как Material Design. При этом он не зависит от библиотеки Cupertino, поэтому у него один и тот же API на всех платформах.

Также недавно мы рассказывали про условные выражения в Dart, про анимацию переходов и про то, как быстро настроить GitLab CI/CD на Flutter-проекте. Подписывайтесь на наш блог, чтобы следить за новостями.

Теги:
Всего голосов 16: ↑16 и ↓0+16
Комментарии2

Изучаем анимацию переходов во Flutter

Пересказ большой статьи в маленьком посте.

Существует много типов анимации для Flutter-приложений. Среди них — Rive-анимация, Hero animations, Progressindicator и т. д. С их помощью можно создавать кастомную анимацию для любого вида работ с системой. Но наиболее базовое решение — библиотека Animations.

Она предоставляет стандартные анимации Material Design. Система движений Material Design состоит из четырех паттернов для перехода между компонентами. Вот они:

  • Container Transform. Он предназначен для переходов между элементами интерфейса, включающими контейнер. Паттерн создает видимую связь между этими элементами.

  • Shared Axis. Его используют для переходов между элементами пользовательского интерфейса, имеющими пространственную или навигационную связь. Паттерн использует общую трансформацию по осям X, Y или Z для усиления взаимосвязи между элементами.

  • Fade Through. Его используют для переходов между элементами интерфейса, не имеющими тесной связи друг с другом.

  • Fade. Он для элементов интерфейса, которые входят или выходят за границы экрана. Например, диалог, который появляется и исчезает из центра экрана.

В шаблонах Shared Axis и Fade Through также нужно использовать библиотеки для навигации. В нашем случае это go_router. В Container Transform и Fade навигацию можно не использовать.

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

Теги:
Рейтинг0
Комментарии0

Разбираемся с yield во Flutter

Начинающие Flutter-разработчики не всегда понимают, для чего нужно ключевое слово yield в Dart. Оно используется в генераторах Stream для пошаговой передачи данных. Это полезно в BLoC для управления состояниями и событиями. 

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

1. Простой генератор:

Stream<int> countStream(int to) async* {
  for (int i = 1; i <= to; i++) {
    yield i; // Постепенно выдаёт числа от 1 до to
  }
}

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

2. Использование в BLoC

class CounterBloc extends Bloc<CounterEvent, CounterState> {
  @override
  CounterState get initialState => CounterInitial();
  @override
  Stream<CounterState> mapEventToState(
    CounterEvent event,
  ) async* {
    if (event is Increment) {
      yield CounterLoading();
      // Представим, что здесь какая-то асинхронная логика
      yield CounterLoaded(newState);
    }
  }
}

Здесь yield используется для отправки различных состояний (например, загрузки и загруженного состояния) в ответ на события.

yield во Flutter — это мощный инструмент для создания асинхронных потоков данных и управления состояниями в BLoC. Он делает код более чистым, понятным и поддерживаемым. А если говорить совсем просто, то yield добавляет значение к выходу потока функции async*. Это как return, но он не завершает функцию.

Подписывайтесь на телеграм-канал руководителя нашего направления Flutter/iOS Саши Ворожищева, чтобы узнать про Flutter больше.

Теги:
Всего голосов 1: ↑1 и ↓0+1
Комментарии0

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

int getCountBagel(List<String> list) {
  list.retainWhere((e) => e == '?');
  return list.length;
}

main() {
  final basket = ['?', '?', '?', '?', '?'];
  final countBagel = getCountBagel(basket); // 2
  print(basket); // [?, ?]
}

Выполнив копирование getCountBagel([...basket]), вы обезопасите себя. Да, это ужасный способ посчитать количество элементов. Но представьте, что вы зависите от стороннего api, к которому у вас нет непосредственного доступа.

Обратная задача: в Dart примитивные типы всегда передаются по значению. Это означает, что если вы передаёте экземпляр примитивного типа в качестве параметра в функцию (или класс) и внутри его изменяете, то оригинальный экземпляр останется неизменным:

void increase(int i) => i++;

main() {
  int i = 0;
  increase(i);
  print(i); // 0
}

Если вы хотите передать что-то по ссылке, то заверните это в класс:

class Wrapper {
  Wrapper(this.i);
  int i;
}

void increase(Wrapper w) => w.i++;

main() {
  final w = Wrapper(0);
  increase(w);
  print(w.i); // 1
}

но такой способ ухудшит SRP (принцип единой ответственности) и усложнит тестирование функции increase... Ответ в комментарии ?

Теги:
Всего голосов 1: ↑1 и ↓0+1
Комментарии1

OTP тестированию не помеха

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

1) endpoint api для которого нужене OTP (one time password)

2) QR код экспорта из google authenticator

Найти: автоматически получать OTP и отправлять его endpoint-у

Решение:

1) Сканируем QR код любым сканером QR кодов, получаем что-то вроде 'otpauth-migration://offline?data=CjIKFEuKYhr.....' , обозначим это за url.
2) Этот url надо раскодировать, есть несколько вариантов как это сделать привожу довольно просто (минимум телодвижений) https://github.com/qistoph/otp_export . Клонируем и выполняем команду
./parse.py 'url'
вывод будет содержать secret это Base32 строчка-ключ обозначим за secret.

3) Осталось выбрать библиотеку для вашего языка реализующую RFC4226/RFC6238 и с помощью sercret и текущего времени в мс. получить OTP

Привожу пример на dart :
Пакет https://pub.dev/packages/otp
Вызов: final code = OTP.generateTOTPCodeString(secret, date.millisecondsSinceEpoch,algorithm: Algorithm.SHA1, isGoogle: true);

Теги:
Рейтинг0
Комментарии0

В Dart 3.0 появились Switch expressions, что позволяет сразу получить значение на основе выражения. Это может выглядеть так:

var x = switch (y) { ... };
print(switch (x) { ... });
return switch (x) { ... };

Сейчас я расскажу, какие преимущества даст новый подход. ?

habr...
habr...

Теперь, когда мы получили погодные данные (Pop.medium и temp = 17.0 ) из приложения Weather Today, наш код будет выглядеть следующим образом:

/// Probability of precipitation
enum Pop { low, medium, high }

enum Things {
  umbrella, // зонт
  raincoat, // дождевик
  windbreaker, // ветровка
  glasses, // очки
  ;

  List<Things> takeExtra(double temp /*Celsius*/, Pop pop) {
    return ...;
  }
}

Для удобства я определил метод takeExtra внутри enum, чтобы иметь доступ к значениям без использования Things. всякий раз. Подумайте, как бы вы реализовали данный метод.

У меня получился вот такой код:

List<Things> takeExtra(double temp /*Celsius*/, Pop pop) => 
    switch (pop) {
      Pop.low when temp >= 10 => [glasses, windbreaker],
      Pop.low when temp < 10 => [windbreaker],
      Pop.medium when temp > 24 => [windbreaker],
      Pop.medium => [umbrella, windbreaker],
      Pop.high => [umbrella, raincoat],
      _ => [glasses],
    };

Заметьте, это выглядит достаточно ёмко и выразительно. Страшно представить, какая цепочка switch case и if'ов могла выстроиться в этом методе. И всё же, используйте с умом данное новшество – лучше написать понятней, чем вычурней.

А в завтрашний поход я возьму зонт и ветровку. ?

Всего голосов 7: ↑7 и ↓0+7
Комментарии1

Ближайшие события

11 – 13 февраля
Epic Telegram Conference
Онлайн
27 марта
Deckhouse Conf 2025
Москва
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань

Как создать неизменяемый список – UnmodifiableListView или List.unmodifiable?

Для начала, давайте попробуем создать неизменяемый (именно unmodifiable, не путать с immutable) список разными способами:

// Dart version: 3.1.0 - 11.0.dev
import 'dart:collection';

void main() {
  // Выводимый тип - List<String>
  const colors = ['?', '?', '?', '?']; // или final

  // Выводимый тип - List<dynamic>
  final colors1 = List.unmodifiable(colors); 
  // используйте List<String>.unmodifiable(), чтобы тип выводился

  // Выводимый тип - UnmodifiableListView<String>
  final colors2 = UnmodifiableListView(colors);
}

Теперь давайте попробуем изменить первый элемент коллекции:

colors[0] = '?';
colors1[0] = '?';
colors2[0] = '?';

В каждом случае мы получим:

Unhandled Exception: Unsupported operation: Cannot modify an unmodifiable list

Неизменяемый список создан, что очень хорошо, однако, здесь есть подводные камни. Сложность алгоритма для List.unmodifiable – O(n), а для UnmodifiableListView – O(1)? Почему?

Продолжение в комментарии ↲

Всего голосов 3: ↑3 и ↓0+3
Комментарии3