Hola, Amigos! Делюсь с вами записью своего доклада с конференции Mobius на тему «Создание indoor-карты здания на Flutter». Рассказал, как реализовать размещение на одном или нескольких экранах внутренней карты здания. А также раскрыл подходы и собственное решение с использованием Flutter.
Hola, Amigos! На связи Павел Гершевич, Flutter Team Lead в Amiga. Сегодня поговорим про отображение HTML-тегов как виджетов в наших приложениях на Flutter.
Чаще всего для этого используется библиотека flutter_html:
Html(data: ‘<p>Hello World</p>’);
Но у нее есть несколько минусов:
– Она больше года не обновлялась, что с одной стороны хорошо, так как она стабильна, а с другой — она уже устаревает. –В ней есть баги. Например, если внутри тега <p> окажется список (<ul>, <ol>), то снизу появляется отступ, равный высоте списка. – Не очень понятная система стилизации. Чтобы что-то изменить, нужно разобраться, как это делается, так как вместо CSS-атрибутов используются собственные подходы.
Пример стилизации, где нужно поменять размер шрифта для всего документа:
Столкнувшись с этими минусами, мы решили перейти на вторую по популярности библиотеку — flutter_widget_from_html_core. Во-первых, она лишена вышеописанных багов. Во-вторых, она модульная, и к ней можно многое прикрутить.
HtmlWidget(‘<p>Hello World</p>’);
Со стилями всё интереснее. Шрифт устанавливается через стандартный TextStyle:
...,
textStyle:
TextStyle(...),
);
Но если нужно его раскрасить или что-то ещё, всё становится сложнее. Продолжение по ссылке.
Это два популярных инструмента для создания анимаций в приложениях на Flutter. Сравнили их плюсы и минусы.
Lottie
Плюсы:
Простота использования: благодаря поддержке JSON, Lottie доступен для разработчиков любого уровня.
Кроссплатформенность: позволяет использовать одни и те же анимации на разных платформах.
Широкое комьюнити: в сети есть большое количество готовых анимаций.
Гибкость: Lottie позволяет настраивать анимацию и эффекты, что дает больше контроля над результатом.
Минусы:
Ограничения по сложности: Lottie не подходит для очень сложных анимаций с большим количеством элементов и эффектов.
Производительность: в некоторых случаях Lottie потребляет слишком много ресурсов, что плохо влияет на производительность приложений.
Rive
Плюсы:
Интерактивность: Rive поддерживает интерактивные анимации, которые реагируют на пользовательские действия.
Мощный редактор: он понятный, функциональный и с ним не нужно погружаться в дебри разработки.
Производительность: с Rive получается быстрая и плавная анимация благодаря формату файлов.
Минусы:
Сложность использования: у Rive более сложный интерфейс, чем у Lottie, новичкам с ним работать трудно.
Размер файлов: Rive-анимации могут быть тяжелыми, и это влияет на вес всего приложения.
Итого: если вам нужны простые и легкие анимации с быстрой интеграцией, Lottie — отличный выбор. Для сложных, интерактивных и высокопроизводительных анимаций лучше подойдет Rive.
Преимущества Rive при разработке Flutter-приложений
При разработке Flutter-приложений используют много типов анимации, о чем мы ранее уже писали. Но Rive всё-таки превосходит большинство из них. Во-первых, у него удобный встроенный UI-интерфейс. Во-вторых, в Rive есть раздел Community, где авторы выкладывают бесплатные анимации.
В-третьих, — и это главное преимущество — в Rive есть State Machine. Это визуальный способ связать анимацию воедино и определить логику, которая управляет переходами. State Machine позволяет создавать интерактивную графику движения, готовую к внедрению в ваш продукт, приложение, игру или веб-сайт.
State Machine включает несколько уровней:
Graph — пространство, в котором мы добавляем состояния и соединяем переходы.
State — анимации временной шкалы, которые могут воспроизводиться в нашей машине состояний.
Transaction — переходы представляют собой логическую карту для State Machine.
Inputs — договор между дизайнерами и разработчиками. Как дизайнеры, мы используем входы как способ управления переходами в нашей машине состояний, назначая их в качестве условий. Разработчики связываются с входами во время выполнения и определяют условия с помощью кода, который может изменить эти входы.
Layers — слой State Machine, который позволяет воспроизводить одну анимацию за раз.
Подробнее о том, как работает Rive и как интегрировать его в проект, в нашем блоге.
WebAssembly (WASM) — это новый способ запуска приложений в браузере. Это не замена JS, а возможность запускать код, написанный на других языках (C++, Rust или C#) вместе с JS. WASM оптимизирует размер и время загрузки и позволяет выполнять его на аппаратном уровне.
Компании, которые имеют дело с графикой (Unity, Figma), используют WASM для повышения скорости работы. Это обеспечивает более плавную работу с интерфейсом за счет снижения зависимости от JS.
Скомпилированное в WASM приложение может улучшить производительность в 2 раза по скорости рендеринга кадров. На видео выше сайт Wonderous, который мигрировал с чистого JS на WASM. Что это значит для Flutter?
А то, что движок Dart компилируется в WASM и обеспечивает более высокую производительность. Это открывает новые перспективы для веб-приложений на Flutter. Можно контролировать каждый пиксель интерфейса на уровне Flutter и наслаждаться производительностью WASM.
Ограничения
- Safari пока не поддерживает WasmGC. Браузеры на iOS, например Chrome, используют WebKit, который пока тоже не поддерживает WasmGC.
- Ни flutter run, ни DevTools не поддерживают WASM в Flutter 3.22. Однако эта функция уже реализована и должна быть доступна в следующем стабильном релизе.
- Пока во Flutter работали над поддержкой WASM, пришлось заменить библиотеки dart:html и package:js. Либы, использующие эти библиотеки, должны мигрировать.
У GetX более низкий порог входа, он проще в освоении, чем BLoC. Он предоставляет простой и понятный API для управления состоянием, маршрутизации и управления зависимостями.
Масштабируемость.
BLoC дает более гибкий и модульный подход к управлению состоянием, и его можно масштабировать на больших и сложных приложениях. BLoC разделяет логику управления состоянием на отдельные блоки, которые легко тестировать. Это облегчает поддержку и обновление кода. Кроме того, в BLoC есть четкое разделение ответственности между слоями приложения, что облегчает масштабирование и улучшает производительность.
Тестирование.
В BLoC есть мощные средства для тестирования потоков событий и состояний, например bloc_test.
Возможности.
GetX предоставляет широкий спектр возможностей для маршрутизации и управления состоянием и зависимостями.
Что же выбрать?
Зависит от конкретных требований проекта и ваших предпочтений. Если приложение небольшое и простое, то GetX может быть более подходящим решением. Он предоставляет понятный API для работы, с ним можно писать меньше кода, что существенно экономит время.
Однако если у вас большое приложение, то лучше выбрать BLoC. С ним вы получите более гибкий и модульный подход к управлению состоянием, а это помогает при масштабировании сложных приложений. Плюс BLoC обеспечит четкую декларативность и читаемость кода.
Это часть статьи Flutter-разработчика Айдара Мавлетбаева — полную версию с кодомищите тут.
Компонентная разработка подразумевает деление мобильного приложения на отдельные компоненты (фичи). За каждый из них отвечает конкретный разработчик — Feature-оунер. Часть времени он посвящает задачам компонента, а часть — технической документации (Roadmap). Feature-оунер также контролирует работу остальных разработчиков, прикрепленных к фиче.
Мы решили перейти на новую методологию на текущем проекте по двум причинам:
У тимлида на проекте было мало времени, его нужно было разгрузить.
Проект смело можно назвать супераппом, он большой. И чтобы новый разработчик полноценно въехал в работу, обычно уходило 3–4 недели. Нам нужно было этот процесс ускорить.
Вот как мы распределили роли:
Методология подходит для больших команд — от 6 разработчиков. Идеально, если часть команды — это стажеры или джуниор-разработчики. В этом случае на позиции Feature-оунеров подходят миддлы, а в их команды можно добавлять стажеров или джунов.
И вот что нам это дало:
Тимлид действительно стал тратить меньше времени на проекте и выполнял только ключевые задачи, что позволило уделить больше времени другим проектам.
Документация проекта оказалась полезной уже в этом проекте. В среднем новый разработчик тратил на 20% времени меньше на ресерч и общение с другими участниками команды, чтобы понять, как работает фича.
На выходе у нас получился полностью задокументированный проект. Даже если мы вернемся к нему через пару лет, мы быстро вспомним, как он реализован, и не будем тратить много времени на ознакомление. А если другая команда начнет с ним работать, для них это не будет темным лесом.
Это короткая версия статьи о компонентной разработке от нашего тимлида Саши Омельяненко — весь текст читайте тут.
Hola, Amigos! На связи Владимир Зевеке, соавтор Flutter. Много. Сегодня поделюсь пакетом screen_brightness, который помогает управлять яркостью экрана. В моём случае, этот виджет понадобился для более эффективной работы barcode.
❗️Screen_brightness работает только на реальных устройствах, на эмуляторе пакет функционировать не будет.
Перейдем к практике: в нашем приложении есть страница, которая должна быть всегда яркой на 70%. Если при переходе на неё экран тусклый, то мы должны поднять яркость до тех самых 70%.
Сделаем это в отдельном методе, который будем вызывать в initState().
Перед изменением уровня яркости экрана, старый показатель мы записали в переменную brightness, чтобы вернуть пользовательские настройки яркости, когда покинем эту страницу.
Интеграция нативных SDK в Flutter-приложение — классный способ использовать функции и возможности, недоступные во Flutter. Для этого используют Platform Channels, которые позволяют Flutter общаться с нативной частью приложения — отправлять и получать сообщения.
Platform Channels — мостики, которые позволяют запускать нативный код из Flutter-приложения. Стандартный декодер обеспечивает эффективную двоичную сериализацию простых значений типа JSON. Сюда относятся логические значения, числа, строки, массивы байт, а также списки и мапы.
Сперва нужно выбрать тип канала в зависимости от потребностей:
MethodChannel: используют в большинстве случаев, когда вызов метода во Flutter запускает нативный метод. Поддерживает асинхронные вызовы методов.
EventChannel: для передачи потоков данных из нативного кода во Flutter.
BasicMessageChannel: для отправки простых сообщений между Flutter и нативным кодом.
Для интеграции нативных SDK чаще всего используют MethodChannel:
Подробнее о том, как как работает интеграция нативных SDK для iOS и для Android и с какими особенности платформ вы можете столкнуться, читайте в нашем переводе.
Как меняется рынок мобильной разработки в 2024 году
Наш Head of Mobile Миша Вассер вместе с другими экспертами мобильной разработки ответил на вопросы Практикума о трендах сферы и прогнозах на этот год. Собрали в этом посте главное.
У iOS-разработки есть будущее
Apple вносит послабления в свои ограничения. Недавно платформаразрешила российским разработчикам принимать платежи вне App Store. Возможно, вскоре iOS-разработчикам вновь станет проще жить.
Flutter — лидер кросс-платформы
В 2023 году доля кросс-платформенной разработкиувеличилась с Flutter во главе. Но нативная разработка всё-таки перевешивает — ее по-прежнему выбирает бигтех и частично средний бизнес.
RuStore набирает ход, а вот российские ОС нет
RuStore приземлила у себя крупные бренды, например Сбер и Альфа-Банк, и развивает собственные инструменты для разработчиков по примеру Google. А вот отечественные операционки затихли. «Аврора» и «РОСА Мобайл» будто сами тормозят развитие внутренними ограничениями.
SwiftUI продолжит набирать популярность
Тренд на SwiftUI у нас пока до конца не оформился, и UIKit всё еще востребован. Но с каждым обновлением SwiftUI становился всё лучше.
Битва Compose и XML
Compose чаще встречается в вакансиях, некоторые компании переходят на него: он удобнее и функциональнее. Но XML пока остается базой.
Ссылку на полный материал оставили выше. А если хотите больше новостей о мобильной разработке, заглядывайте в телеграм-канал Саши Ворожищева, Head of Flutter/iOS.
Изменения в скролле. Тут завезли оптимизацию и гибкость в управление поведением.
Виджет AnimationStyle. Он позволяет юзерам менять стандартное поведение анимации в виджетах. А разработчики с его помощью могут переопределять кривые и продолжительность анимации.
Adaptive Switch. Компонент выглядит и ведет себя как нативный на macOS и iOS, а в других случаях — как Material Design. При этом он не зависит от библиотеки Cupertino, поэтому у него один и тот же API на всех платформах.
Как вы уже заметили, иконку можно отдельно настроить для Web, Windows и MacOS. Рассмотрим ещё другие настройки пакета:
– min_sdk_android (определяет минимальную поддерживаемую версию SDK); – generate (нужно ли переопределять иконку для данной платформы); – image_path (путь до изображения, которое будет иконкой); – image_path_android (путь до изображения, специфичного для платформы android, которое будет иконкой, только для Android); – image_path_ios (путь до изображения, специфичного для платформы ios, которое будет иконкой, только для iOS).
Запускаем пакет командой flutter pub run flutter_launcher_icons.
Присоединяйтесь к нашему телеграм-каналу Flutter. Много, который мы ведем с командой мобильных разработчиков. Там мы делимся своим опытом и полезными советами)
Hola, Amigos! На связи Вова Зевеке, Flutter dev Amiga и соавтор телеграм-канала Flutter.Много. Сегодня расскажу, как сделать свой splash screen с помощью пакета flutter_native_splash.
Настроим pubspec.yaml. Добавим основную зависимость flutter_native_splash: ^2.3.10, плюс в конце файла укажем детальные настройки нашего сплеша.
Тестирование Flutter-приложений в базовых принципах не сильно отличается от тестирования нативных. Но есть несколько интересных особенностей:
Все элементы Flutter-приложения — виджеты: это упрощает тестирование интерфейса и функциональности, обеспечивает единообразие интерфейса.
Тестирование на Flutter быстрее: платформенно-специфические функции тестируются отдельно на iOS и на Android, а остальные — на какой-то одной.
Flutter предоставляет собственные инструменты для тестирования виджетов и интеграционного тестирования.
Есть и сложности:
Отслеживание трафика: Dart обычно использует высокоуровневые библиотеки для HTTP-запросов, и они инкапсулируют низкоуровневые детали сетевого взаимодействия — это затрудняет доступ или мониторинг данных.
Проблема решается подключением прокси-сервера. Лучше всего добавить этот функционал в инженерную панель.
При тестировании различий UI/UX на разных платформах мы замечаем типичные проблемы: анимация, свайпы и отображение системных диалоговых окон.
Поэтому не стоит фокусироваться на всех кнопках. Лучше обращать внимание только на существенные различия. Тут помогает общение с сообществом.
Чтобы работать с Flutter-приложениями, мы используем FlutterDevTools. Это комплект инструментов для отладки и профилирования в экосистеме Flutter. Также применяем голден тесты, а для автоматизации — Appium. Подробнее про это рассказываем в отдельной статье, а про Flutter — в телеграм-канале.
Советы от Team Lead для подготовки к первому собеседованию
Hola, Amigos! На связи Сережа Климович, Mobile Team Lead Amiga и соавтора Flutter. Много. Начну с того, что у начинающих мобильных разработчиков есть несколько грейдов: «стажер», «junior» и «junior+». В зависимости от скиллов будут меняться требования к сотруднику и условия сотрудничества. Оценивайте свои знания и умения трезво, не стыдно чего-то не знать.
Что должен знать даже стажер?
– Минимально в Dart: типы данных и переменные, функции, классы, Control flow statement, примитивные структуры, литералы, print, понимание null safety. – В Flutter: runApp, MaterialApp, Scaffold, Align, Container, Flex, Expanded, Spacer, ListView, Text, простая навигация между двумя экранами, разница между Stateless и Stateful виджетами. – Уметь устанавливать и настраивать IDE, dart и flutter для разработки. Понимать суть работы удаленных репозиториев Git (GitHub / GitLab).
Junior должен знать всё, о чем я написал выше. Плюс:
– Иметь практический опыт основ объектно-ориентированного и асинхронного программирования. – Понимать механизм управления локальным состоянием. Знание виджетов для верстки экранов, способов взаимодействия с пользователем (кнопки, жесты и т.п.). – Базовое управление проектами. Обязательно: Pub и pub.dev, pubspec.yaml. – Уметь взаимодействовать с git через IDE. – Понимать HTTP запросы, например get/post. – Знать форматы запросов и ответов, например JSON и пакет json_serializable.
Мнение: почему мультиплатформа Kotlin не приживется в мире разработки
Спойлер: из-за нелюбви к изменениям и дефицита специалистов.
Наш руководитель направления Flutter и iOS Саша Ворожищев делится основными тезисами статьи о судьбе Kotlin Multiplatform Mobile (KMM). Автор статьи — разработчик Донн Фелкер (Donn Felker) — не пророчит KMM мировой славы. И вот почему.
Люди не любят что-то менять. Особенно программисты. Редко встретишь iOS-разработчика, который перешел на Android. И наоборот.
Кросс-платформа чаще не оправдывает надежд. Мы уже не раз наблюдали попытки создать кросс-платформенные суперхиты — взять к примеру Flash и ActionScript, Mono и Xamarin, — но ни одна из этих технологий так и не покорила мир программирования.
Сейчас конкуренцию КММ может составить только 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-разработчики не всегда понимают, для чего нужно ключевое слово 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, но он не завершает функцию.
Что добавить в CI при настройке GitLab CI/CD на Flutter-проекте?
Вот два примера команд для Static-проверок от нашего Flutter-разработчика Саши:
dart-metrics-analyze
Поможет нам проанализировать код, выявить ошибки стиля и проблемы, которые могут повлиять на качество кода и сложность его поддержки.
dart-metrics-analyze:
stage: static
interruptible: true
before_script:
- flutter pub get
script:
- flutter pub run dart_code_metrics:metrics analyze --fatal-style --fatal-performance --no-fatal-warnings --reporter=console lib
tags:
- ci
dart-metrics-check-unused-files
С помощью этой задачи можно проверить, все ли файлы в коде действительно использованы. Лишние файлы могут усложнять код и увеличивать время его компиляции.
dart-metrics-check-unused-files:
stage: static
interruptible: true
before_script:
- flutter pub get
script:
- flutter pub run dart_code_metrics:metrics check-unused-files --fatal-unused --exclude="{lib/application/core/bloc/void_action_bloc.dart,lib/util/log.dart}" lib
tags:
- ci
В обоих примерах используем проверки Dart Analyze. В результате мы получим чистый код, где нет лишних файлов. Еще можно добавить проверки на неиспользуемые переводы, на совместимость сгенерированных файлов локально и в репозитории.