Мой опыт на Flutter

 Публичный пост
18 июня 2021  7251

Intro

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

  • Flutter для меня
  • Свой опыт \ Проекты
  • Выбор State Managment(BLoC, Redux и другие) \ Flutter Files
  • Разное на мобиле\Пакеты
  • Flutter web+macOS и другие
  • Null safety

Flutter для меня

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

Свой опыт \ Проекты

Путь во Flutter я начал с возможности сделать маленький проект на пару страниц для человека из бизнеса, проект не пошел, но технология проросла в моем уме и через полгода я начал https://medium.com/it-challenge с упором на реализацию плеера для Apple Music на Flutter.

Meows.app
Meows.app

Пол года на изучение и релиз первой версии приложения, еще пол года улучшений и в феврале я ухожу с позиции Team Lead "Европлан" (Angular+.Net Core) на Flutter developer в "Лигу ставок" - на тот момент одно из немногих мест с хорошей ЗП на Flutter.
Моё выступление на митапе Ozon:

Лига Ставок

Проект в лиге - это built_redux, dioc, BLoC на стримах и много кода на 5 разрабов(на тот момент). Причем я пришел не в основной проект, а на его ответвление и занимался архитектурой для построения нескольких приложений из одной кодовой базы и приведения кода над которым работали подрядчики(6 месяцев) к рабочему варианту - мне дали двух разрабов аутсорсеров, и через 2 месяца почти готовый merge форка проекта и рабочая версия платформы остались компании, а я пошел пилить проект с нуля для zfx.com.

zfx.com

Я начал пилить биржу(мобильный клиент) для международной версии системы, сейчас у нас в работе большая версия с личным кабинетом, торговлей и деньгами(ввод\вывод и другое), я снова Team Lead и у нас 5 разрабов :)

Очень скромная первая версия
Очень скромная первая версия

State Managment\ Flutter Files

Когда я начал изучать Flutter самой большой проблемой стал выбор как сделать State Managment в моем приложении. Большое изучение вариантов и статей привело меня к моей вариации flutter_bloc от Felix Angelov, почему моей - потому что у меня есть два ключевых отличия:

  • структура папок - как фичи

  • Реализация event лежит внутри event(файл bloc почти пустой)


Больше всего мне нравится в нем понятная работа - есть стрим событий и state текущего состояния от которого мы делаем декларативный UI.

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

Один из самых больших минусов BLoC - это бойлерплейт, но я его победил, когда написал Flutter Files - это расширение для генерации файлов на основе настроек вашего проекта и ваших custom template, например у нас генерация сразу готовая страница со всем обработчиками, логикой вызова загрузки данных, описание навигации, темы и DI.

Разное на мобиле\Пакеты

Для DI используем GetIt с описанием в отдельный файл и подключением на старте, получение инстансов объектов делаем в начале файла, а не через конструктор - для упрощения - в целом нормально. Provider через Context почти не используем - на мой взгляд зависимости надо передавать более явно.

Для локализации взяли - https://localizely.com/ у них есть пакет для обновлений переводов по воздуху.

Для локального кэширования используем собственную обертку над hive
Локальную базу с запросами я не использую, довольствуюсь key-value storage.

Аналитика - [firebase]написанный(https://pub.dev/publishers/firebase.google.com/packages) , appmetrica_sdk, sentry

Для http используем dio - у него нормальные interceptor.

Есть websocket, grpc пакеты.

Для навигации используем navme

Для длительных задач предпочитаю использовать computer, который запускает выполнение в отдельном потоке с внутренней очередью выполнения задач.

Вообще есть большой пункт - не используйте кодогенерацию через build_runner - чем больше ваш проект, тем больнее вам будет, проект в лиге обновлял модели 2-3 минуты на топовом macbook pro 2020 года, обновлять приходилось модели часто и падал он тоже часто и без нормальных ошибок =( Сейчас мы используем Dart Data Class Generator
для генерации базового кода.

В целом с пакетами все достаточно хорошо, особенно если надо две платформы.

Push - мы используем firebase, все отлично)

Большая поддержка SDK в Huawei

Flutter web+macOS и другие

Проект написанный для мобилы достаточно легко запустить на web или macos - но работать он будет только если у вас плагины есть для каждой платформы и\или вы написали немного оберток над платформо зависимыми частями. Приложения для macOS - быстро компилятся, но если ваш продукт в первую очередь мобильный, то лучше тестить на ios\android даже во время разработки. Web часть более сложная и разрабатывать ее менее удобно - дебагер глючит, но с каждым релизом там все лучше - самая большая проблема нет SSR и непонятно когда будет.
https://github.com/doppio-dev/iXn - пример на web\macos уже устаревший, но там есть базис BLoC и сборка через github.

Null safety

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

P.S. пишите ваши вопросы, буду отвечать и обновлять статью.

43 комментария 👇
Андрей Писков человек-оркестр (директор по IT-продуктам) 19 июня 2021

Обычно вся эта ненативщина работает до очередного глобального обновления держателя платформы (api и пр.). Потому что условный эпл раньше wwdc не придет к тому же flutter, мол, ребята, готовьтесь.

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

Знал лично несколько примеров любителей того же Xamarin несколько лет назад (ios 7?), которые так очень больно обожглись (обновления не было пару месяцев уже после официального релиза айоси) и зареклись в будущем повторять опыт.

  Развернуть 1 комментарий

@piskov, Flutter насколько я понимаю меньше зависит от натива - в основном от рендера движка нативной платформы. Насколько я слышал - Apple сотрудничает с Flutter Team.

  Развернуть 1 комментарий

@Gorniv, а виджеты, экстеншны(например rich push notifications), аппклипы можно на флаттере писать или тут уже придется на нативке через икскод?

  Развернуть 1 комментарий

@aaisataev, все перечисленное реализовывается нативно без участия флаттера

  Развернуть 1 комментарий

@VladimirBrejcha, если у меня все ui компоненты написаны на флаттере, то мне придется их дублировать в свифт, чтобы использовать в виджете или пушках, например?

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

  Развернуть 1 комментарий

@aaisataev, придется дублировать, если нужна единая дб то делать нативно и пробрасывать во флаттер

  Развернуть 1 комментарий

@aaisataev, логику ты делаешь на flutter, а из нативной части ее вызываешь через bridge. Обычные пуши работают через пакет, а вот rich push надо рисовать в нативе.

  Развернуть 1 комментарий

@Gorniv,

Насколько я слышал - Apple сотрудничает с Flutter Team.

Можно поподробней про это?

  Развернуть 1 комментарий

@Grekov, блин, никаких пруфов сходу не нашел- можете считать, что я не прав)

  Развернуть 1 комментарий

Какое будущее, на твой взгляд, ждет Флаттер, учитывая, что под боком развивается КММ?

  Развернуть 1 комментарий

@ultrav1olence, отличное будущее ждет Flutter, самое лучшее. а КММ вообще не конкурент, так как там нет UI\UX. Flutter - это возможность быстро и качественно писать единую кодовую базу для ВСЕХ платформ(платформы, стабильность и скорость становятся все лучше)

  Развернуть 1 комментарий

@Gorniv,

ВСЕХ

Виндовс/линукс тоже? Я помню, вроде хотели для них поддержку сделать, но получилось ли?

  Развернуть 1 комментарий

@kurumpa, Microsoft очень активно с Flutter, есть windows(не тестил) над UWP работают. Linux - https://ubuntu.com/blog/flutter-and-ubuntu-so-far , то есть все прекрасно, если даже не сейчас то в будущем)

  Развернуть 1 комментарий

@ultrav1olence, это абсолютно разные вещи и решают разные проблемы. Я думаю что флаттер успешно отожрет нишу небольших мультиплатформенных апок. KMM - это возможность один раз написать бизнес логику и уменьшить связанные с ней риски для больших приложений.

  Развернуть 1 комментарий

@dakar, что значит небольших?) Сейчас становится все важнее time to market и размер команды - в этом нет равных именно Flutter.

  Развернуть 1 комментарий

@Gorniv, Xamarin и React девы тоже так говорят) Лет десять никак нативщиков не поборят)
Как я писал ваше флаттер отличное решение для небольших и быстрых MVP.

  Развернуть 1 комментарий

@dakar, Xamarin и React не строят каждый пиксель итогового приложения сами. Xamarin - или тупой неповоротливый Xamarin.Forms или нативные view - суть KMM. React - тупой мост, использование js,и проблемы производительности отрисовки - единственный плюс - публикация изменений без релиза приложения.

  Развернуть 1 комментарий

@Gorniv, еще раз - Флаттер лучше их и кмк будет заслуженно доминировать в их нише. Нативные проекты и дальше будут там где нужна производительность, легкость поддержки кодовой базы и более тесная работа с ОС.
Ну а срачам мультиплатформ vs нейтив уже лет 25)

  Развернуть 1 комментарий

@Gorniv, KMM - вообще не про UI. Это нативный инструмент

  Развернуть 1 комментарий

@dakar, приложений которые надо делать на нативе с каждым годом будет меньше - я про это) Их будет много, но тенденция будет на рост мультиплатформ, так как ресурсы девайсов позволяют. Для меня KMM - это либа с логикой, которую можно и на .net core(Xamarin) написать и использовать - типа в чем фишка KMM - только количество разрабов на kotlin рядом с мобилой, которые его продвигают :D интеграция KMM в iOS - это так себе :D

  Развернуть 1 комментарий

@Gorniv, срачу нейтив против мультиплатформы уже лет 25 и я не вижу смысла сжигать в него ещё и этот вечер) Я давно понял для себя что это отдельные рынки и никто никого не завоюет.

  Развернуть 1 комментарий

@Gorniv, разница между KMM и нативным Xamarin (без Forms) это то что KMM не покрывает все API платформы как это делает Xamarin. Он чисто для бизнес-логики, в то время как на Xamarin можно делать нативные UI и почти не терять в производительности по сравнению с полностью нативной разработкой.

Преимущество KMM в том что он менее инвазивный и его можно воткнуть в уже существующий проект на Swift, в то время как мобильный .NET не рассчитан под встраиваемость и весь проект нужно делать с нуля на C# в Visual Studio.

  Развернуть 1 комментарий

@ultrav1olence, а как насчет того, что compose уже вот-вот релизнется а JB активно делают compose MPP?

  Развернуть 1 комментарий
Георгий Гошанов Фронтенд разработчик 18 июня 2021

Мы на проекте использовали GetX (https://github.com/jonataslaw/getx) для DI, state-management и роутинга. По сравнению с BLoC можно управлять стейтом с заметно меньшим бойлерплейтом.

Но вот с DI в итоге подзапуталось, контроллеры уничтожались когда не нужно, и наоборот не обновлялись когда это было необходимо (возможно из-за нашей неопытности с Flutter и GetX).

Использовал ли ты что-то из экосистемы GetX?

  Развернуть 1 комментарий

@Goshanov, бойлерплейт - это не только вред, но и разделение логики и UI. GetX - это скорее зло, так как позволяет говнякать код, поэтому использовать надо очень аккуратно. Ну и принцип - все на статиках и расширениях - не лучшее решение для большого проекта.

  Развернуть 1 комментарий

С текущей реализацией flutter web, SSR там не будет никогда(

  Развернуть 1 комментарий

@dskr, в целом они могут сделать отдельную реализацию для отдачи контента ботам - нам же главное SEO =)

  Развернуть 1 комментарий

А что с MobX? А Реакте с ним одно удовольствие, а во Флаттере? Тоже поковырять хочу.

  Развернуть 1 комментарий

@glebkudr, слышал что он хорош, но я не пробовал его + та реализация, которую мне показывали была с кодогенерацией через build_runner, а ее очень не хочу)

  Развернуть 1 комментарий

Спасибо за статью.
Какие ресурсы посоветуешь для ознакомления? Понятно, что в основном нужно курить flutter.dev, но всё же.

  Развернуть 1 комментарий

@buzur, курс на udemy и статьи на habr

  Развернуть 1 комментарий

Спасибо за статью.
Мне нравится Флаттер, но переживаю про поиск работы в будущем. Сейчас, например, вакансий iOS девелоперов во много раз больше чем Флаттер. Как думаешь на расстоянии нескольких лет сильно ли изменится это соотношение?

  Развернуть 1 комментарий

@igor-beaver, flutter постоянно растет, те кто работает сейчас с ним - будут востребованы очень-очень)

  Развернуть 1 комментарий

@igor-beaver, если что, пересесть не долго) Главное не быть stackoverflow-developer с фокусом на один фреймворк

  Развернуть 1 комментарий
Roman Ventskus Конвертирую кофе в код 18 июня 2021

В тред призывается человек с опытом Flutter и Swift UI для развернутого комментария о плюсах и минусах каждой из платформ =)

Сам пишу на Flutter, но интересно мнение сообщества, готов ли Swift UI к полноценному использованию и какие плюсы сулит по сравнению с Flutter

  Развернуть 1 комментарий

@roman_v, у меня нет опыта SwiftUI, но есть опрос людей:

  1. SwiftUI - это не мультиплатформа
  2. Для нормальных проектов надо ждать когда минимальная версия поддержки будет 13 - у нас сейчас 10, то есть ждать 2-3 года минимум.
  3. Сейчас он лагает, особенно на сложных кейсах UI, но это будущее для iOS во многом.
  Развернуть 1 комментарий

@roman_v,
Пишу на Flutter и пишу на iOS, могу сказать что
SwiftUI готов к использованию с iOS14 (хотя и на 13 используют, но это менее комфортная история). SwiftUI хорош, но плюсы и минусы здесь будут всё те же что и в native vs cross-platform :)

  Развернуть 1 комментарий
Георгий Перепечко старший красильщик кнопок 21 июня 2021

Крутая статья, за наводку на Dart Data Class Generator прям отдельное громадное спасибо, выглядит как очень крутая альтернатива build_runner.

на самом деле, стэк очень похож на наш -- потому хотел активно поспрашивать:

  • navme

тут сами используем просто Navigator 2, но оно получается костыльненько местами; нет опыта, насколько эта штука дружит с вложенными навигаторами (когда у каждого таба меню свой стэк истории)?

  • get_it

используем в основном для общения между взаимозависимыми блоками, но периодически ловим в разработке странные баги после hot reload'а (обычно hot restart их лечит); не сталкивались?

  • hive

если не секрет, что храните там? просто данные с сервера пришедшие? правильно понимаю, что идея просто в том, чтоб в памяти их не держать постоянно и минимизировать походы на сервер?

ну и (как, в основном, фронтендеру) интересно: часто ли возникают проблемы, которые сложно решать без опыта в мобилке? мы просто в довольно специфичной сфере -- и упираемся в отсутствие опыта на мобилке с завидной периодичностью, интересно понять общую температуру по больнице.

  Развернуть 1 комментарий

@merelj, navme - у нас есть встроенные навигаторы - вроде норм) navme - это пакет, который я написал для Navigator2 =)
get_it - вроде все нормально - вы все зависимости на старте регистрируете?
hive - про как кэш, с доступом по ключу и ограничением времени жизни.
У нас в проекте полностью готов дизайн - поэтому сложностей по рабочему проекту нет, по пэт - приходиться думать, но это на мой взгляд не проблема)

  Развернуть 1 комментарий

@Gorniv,

  • попробую navme где-нибудь на пет-проджекте тогда: надоел бойлерплейт)
  • с get_it -- да, все сразу регистрируем; может, GetIt.I.allowReassignment = true стреляет (используем его когда юзер разлогинивается)
  • про hive понял, нужно будет посмотреть поближе -- авось пригодится)
  • у нас в основном не с дизайном проблема, а со всякими поднятиями из бэкграунда в андроиде :/ но вроде пока справляемся, просто интересно было понять, насколько часто подобные штуки жизнь портят :)
  Развернуть 1 комментарий

@merelj, GetIt.I.allowReassignment так не делаем, макисмум - это Lazy.
Мне нормально)

  Развернуть 1 комментарий

@Gorniv, а любопытства из: где вы регистрируете в get_it все? просто в main? или ближе к месту использования блока -- и если нужно пересоздать -- просто разрегистрируете и регистрируете заново?

  Развернуть 1 комментарий

@merelj, рядом с фичей такого вида:

class DepositGatewayDiDelegate implements DiDelegate {
  @override
  Future<void> register(GetIt container, {bool ensureInitialized = true, Directory directory, bool forTest = false}) async {
    container.registerFactory(() => DepositGatewayTheme());
  }
}
и на старте приложения все Delegate регистрируем.
    Future<void> registerWithDelegate(DiDelegate delegate, {bool ensureInitialized = true, Directory directory, bool forTest = false}) async {
    await delegate.register(this, ensureInitialized: ensureInitialized, directory: directory, forTest: forTest);
  }
Разрегистрацию используем только в тестировании - когда подставляем моки.
  Развернуть 1 комментарий

😎

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

Что вообще здесь происходит?


Войти  или  Вступить в Клуб