IT-инфраструктура для бизнеса и творчества
Разработка
Mad Brains

Мобильное приложение на Flutter, часть вторая: стоимость, сроки, подводные камни

Мы в Mad Brains очень внимательно подходим к выбору технологий разработки, поэтому к кроссплатформе шли несколько лет. Нас постоянно в ней что-то не устраивало: набор компонентов, производительность, выразительность языка.

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

О чем статья

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

Как устроены кроссплатформенные фреймворки?

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

  1. «Приложения-браузеры» — Cordova, PhoneGap, Ionic — мобильный сайт, завернутый в оболочку приложения с единственной веб-страницей, растянутой на весь экран. Все проблемы мобильного сайта остаются на месте, попытки сделать html-компоненты похожими на стандартные работают с переменным успехом, JS опять же.
  2. «Сделай сам» — Qt и C++, Kotlin Multiplatform — как езда на машине с ручной коробкой передач по бездорожью... с педальной тягой... и табуретом вместо кресла. Есть доступ к самому низкому уровню, где почти нет ничего готового. Либо нужно писать все самостоятельно, вплоть до отрисовки внешнего вида кнопок, либо реализовывать отдельно для каждой платформы связь со стандартными компонентами. Получить выгоду в таком подходе получается только для специфических задач, обычно все наоборот.
  3. «Уравнители» — Xamarin, React Native — решения, которые стараются магическим образом преобразовать свой код в стандартные компоненты платформ. Этот подход напоминает телевизионную игру «Стенка на стенку», где игроку нужно встать в такую позу, чтобы попасть в нужную форму. Только в данном случае формы сразу две, а поза одна. Например, если в iOS есть возможность добавить кнопке тень и закругление, а в Android — обводку и закругление, то может случиться, что получится воспользоваться только закруглением, а остальное придется делать отдельно для каждой платформы.
  4. «Дайте холст, мы со своим пришли» — Unity и пр. игровые движки, Flutter–подход чем-то похож на первый тип, но за основу берется не веб-страница, а самый низкий уровень из возможных — уровень отрисовки на экране. Другими словами, фреймворк буквально управляет состоянием каждого пикселя максимально близко к железу, а не пытается найти похожий элемент в каждой платформе. Так чем же это лучше подхода «Сделай сам»? По факту только тем, что все сделано за нас и этим можно удобно пользоваться, как машиной с автоматической коробкой передач, да еще и с климат-контролем.

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

Как работает Flutter?

Немного технических деталей реализации. На самом верхнем уровне мы оперируем виджетами (Widget). В корне Flutter идея, что все есть виджет (не без исключений, конечно же). Виджеты отрисовываются на канвасе с применением графической библиотеки Skia и отправляются на обработку платформе. Платформа отображает канвас и пересылает обратно события (пользовательское взаимодействие, данные с датчиков и тп.).

Наглядная демонстрация технических деталей работы Flutter

Такое взаимодействие можно условно разделить на 3 слоя.

Flutter system overview

Embedder — самый низкий уровень, непосредственный контакт с платформой. Определение потоков для работы, переадресация событий и прочие низкоуровневые вещи, которые транслируют данные и события между миром Flutter и платформой. Для каждой платформы (iOS, Android, Web, Desktop) эта часть пишется отдельно.

Engine — базовая часть Flutter, оптимизированная и написанная на C/C++, но уже не зависящая от платформы. В нее входит дальнейшая переадресация данных и событий, отрисовка с помощью библиотеки Skia, работа с изолятами и прочие низкоуровневые процессы самого Flutter.

Framework — то, с чем мы непосредственно работаем в момент создания приложения. Готовые виджеты для создания интерфейса, управление лейаутом, отрисовкой и состоянием деревьев виджетов, элементов и рендер объектов.

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

Поддержка новых версий операционных систем

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

Другим вариантом может стать воссоздание компонента самостоятельно из готовых вариантов или подсмотрев исходники — они находятся в открытом доступе. Поддержка Material Design во Flutter-компонентах на данный момент реализована полнее, чем на Android, для которого этот Material Design и придумывался в свое время.

Поддержка аппаратных функций

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

А как же нативные компоненты?

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

Производительность

Кроссплатформенные решения прошлых поколений научили нас, что за универсальность приходится платить. Чаще всего под нож попадает производительность приложения. Достаточно вспомнить проблемы со скроллом в React Native. Резонно задаться вопросом, как дела с производительностью у Flutter?

Сами разработчики отвечают на этот вопрос так:

“You can expect excellent performance. Flutter is designed to help developers easily achieve a constant 60fps.”

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

Код Dart компилируется в нативный, а это означает отсутствие трат ресурсов на интерпретацию кода во время выполнения. Виртуальная машина Dart приспособлена для создания и уничтожения огромного количества объектов, что позволяет работать с огромным количеством визуальных элементов на экране без каких-либо проблем. Графический движок Skia специализируется на работе с 2D-графикой и позволяет отрисовывать все с частотой 60 кадров в секунду.

Это все прекрасно, но давайте посмотрим на числа. В интернете легко можно найти 2 независимых исследования этой темы:

  • Коллеги из inVerita в своем материале сравнили вычислительную мощность Dart с нативными языками, а также производительность UI-компонентов Flutter, React Native и натив на iOS и Android. Вывод вполне ожидаемый — нативные решения в среднем оказались наиболее производительными, но Flutter и Dart не сильно отставали, а местами даже опережали натив, чего не скажешь о React Native.
  • Bram De Coninck написал про то, как сначала сделал одинаковое приложение на Xamarin Forms, React Native, Flutter, iOS и Android. А затем сравнил их производительность. В данном эксперименте Flutter опять показал себя близким по производительности к нативным реализациям, а Xamarin Forms и React Native снова остались не у дел. В данном исследовании интересно принять во внимание еще и первую часть со сравнением времени, потраченного на реализацию, оно тоже вполне сопоставимо с написанием приложения под нативную платформу — одну. А в случае с Flutter мы получаем реализацию сразу на 2 платформы, то есть примерно в 2 раза быстрее.

Исключительные черты Flutter

Помимо всего перечисленного, есть еще несколько вещей, выделяющих Flutter:

  • Open Source. Открытый код, доступный для изучения и изменения. Можно без труда понять, что происходит внутри, и даже поправить при желании. Если Google решит отказаться от этого проекта, он будет жить за счет сообщества.
  • Инструменты. Очень удобные компоненты, значительно упрощающие работу. Один из них hot reload. Теперь не нужно после каждого изменения ждать компиляции и запуска приложения для проверки.
  • Документация. Подробная документация по каждому аспекту, информативные видео на YouTube, мероприятия и конференции — постоянные потоки полезной информации со всеми разъяснениями.
  • Проверенные подходы. Архитектурная часть взята с проверенных на вебе решений. Это позволило не изобретать велосипед, а опираться на опыт прошлых мировых разработок. Для мобильных разработчиков это непривычно, т.к. они привыкли изобретать новую архитектуру каждый год, что в узких кругах это стало своеобразным мемом. Пора уже использовать что-то проверенное.
  • Производительность. Самый низкий уровень отрисовки, управление каждым пикселем, использование Skia под капотом (графическая библиотека, давно зарекомендовавшая себя), никакой интерпретации на лету - только компиляция в машинный код. На выходе - 60 кадров в секунду, работа без задержек.

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

Ложка дегтя

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

  • Новизна технологии. Есть у всего нового свои детские болезни. Не обошло это стороной и Flutter, особенно в первое время после официального релиза, когда все обратили особое внимание на технологию. Баги есть везде, но в данном случае они воспринимаются как что-то очень критичное, так как кредита доверия еще не образовалось, большие игроки на тот момент еще не включились в игру. Сейчас с этим лучше, сообщество растет, ошибки активно исправляются. Только в последнем релизе было влито более 3000 исправлений.
  • Dart. Главная боль для любого мобильного разработчика, избалованного Kotlin и Swift. Отдельный язык программирования, который отстает от крутости последних наработок Kotlin и не дотягивает до лаконичности Swift. Да и специфика однопоточности языка накладывает свои сложности в понимание, как с этим работать.
  • Нехватка кадров. Из вышеперечисленного вытекает, что найти разработчиков, особенно опытных, непросто. Хорошо, что в IT-сфере люди привыкли постоянно обучаться и искать новые подходы и решения. Так, например, Flutter из-за своей специфики позволяет быстро влиться не только мобильным разработчикам, но и веб-разработчики находят много привычного и удобного.

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

Выводы

Flutter — молодой SDK, у которого есть шанс стать первым массовым кроссплатформенным решением. Да, он не идеален, но наиболее близок к нему.

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

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

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

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

Например, если потребуется, чтобы Tab Bar превращался в боковую панель при повороте, то Flutter сделает это легко, в то время как на нативе это заставит помучиться. Благодаря всему этому, разрабатывая на Flutter, программисты экономят время, а клиент — бюджет.

Другие статьи из этой серии

{ "author_name": "Mad Brains", "author_type": "self", "tags": ["\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b","flutter"], "comments": 20, "likes": 13, "favorites": 44, "is_advertisement": false, "subsite_label": "dev", "id": 143489, "is_wide": true, "is_ugc": true, "date": "Mon, 20 Jul 2020 15:56:54 +0300", "is_special": false }
(function () { let cdnUrl = `https://specialsf378ef5-a.akamaihd.net/SelectelBranding/images/` let previousArticleNumber = null let currentArticleNumber = 0 let platform = 'Desktop' let articles = [ // { // name: 'camera', // url: `${cdnUrl}CameraCat`, // text: 'умную камеру для\u00A0наблюдения за\u00A0котиками', // link: '1', // }, { name: 'chill', url: `${cdnUrl}ChillCat`, text: 'трекер, который подскажет, когда пора отдохнуть', link: 'https://vc.ru/promo/288561-eye-tracker', }, // { // name: 'cloud', // url: `${cdnUrl}CloudCat`, // text: 'котика: даёшь ему «пять», а\u00A0он делает бэкап в облако', // link: '3', // } ] let buttonCycle = document.querySelector('.button--cycle') let textField = document.querySelector('.selectel-footer-subtitle') let imageAgent = document.querySelector('.image--agent') let banner = document.querySelector('.selectel-footer') buttonCycle.addEventListener('click', cycleClick) let media = window.matchMedia("(max-width: 570px)") media.addEventListener('change', matchMedia) function matchMedia() { if (media.matches) { platform = 'Mobile' } else { platform = 'Desktop' } update() } matchMedia() function cycleClick(event) { if (event) { event.preventDefault() event.stopPropagation() } window.open('https://vc.ru/tag/selectelDIY', '_blank') //cycle(event) } function cycle(event) { // incrementArticleNumber() textField.innerHTML = generatedText() imageAgent.src = articles[currentArticleNumber].url + platform + '.svg?5' imageAgent.setAttribute("class", "") imageAgent.classList.add('image--agent', articles[currentArticleNumber].name) banner.href = articles[currentArticleNumber].link } function update() { banner.href = articles[currentArticleNumber].link imageAgent.src = articles[currentArticleNumber].url + platform + '.svg?5' textField.innerHTML = generatedText() } function incrementArticleNumber() { previousArticleNumber = currentArticleNumber if (currentArticleNumber >= articles.length - 1) { currentArticleNumber = 0 } else { currentArticleNumber++ } } function generatedText() { let defaultText if (platform === 'Desktop') { defaultText = `Мы тут собрали %text%. Хотите почитать?` } else { defaultText = `Мы тут собрали %text%.` } return defaultText.replace('%text%', articles[currentArticleNumber].text) } function getRandom(min, max) { min = Math.ceil(min) max = Math.floor(max) return Math.floor(Math.random() * (max - min + 1)) + min } (function create() { currentArticleNumber = getRandom(0, articles.length - 1) cycle() let page = document.querySelector('.page--entry') if (page) { function insertAfter() { let parents = page.querySelectorAll('[data-id="7"]') let referenceNode = parents[0] referenceNode.parentNode.insertBefore(banner, referenceNode.nextSibling); loaded() } setTimeout(() => insertAfter(), 0) } }()) function loaded() { banner.classList.add('loaded') } loadImages([ `${cdnUrl}CameraCatDesktop.svg`, `${cdnUrl}ChillCatDesktop.svg`, `${cdnUrl}CloudCatDesktop.svg`, `${cdnUrl}CameraCatMobile.svg`, `${cdnUrl}ChillCatMobile.svg`, `${cdnUrl}CloudCatMobile.svg`, ]) function loadImages(urls) { return Promise.all(urls.map(function (url) { return new Promise(function (resolve) { var img = document.createElement('img'); img.onload = resolve; img.onerror = resolve; img.src = url; }); })); } }())
0
20 комментариев
Популярные
По порядку
Написать комментарий...

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

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

1

JS-ники любят писать по 10ку новых библиотек каждый день, да. Мобильщики же просто буквы тасуют в аббревиатурах(MVVM, MVP, MVI, VIPER и тп), по сути не сильно уходя от MVC

1

много ошибок в статье.
Kotlin multiplatform вообще не о том
flutter не компилируется в нативный код. Он работает в своей VM, которая уже работает в VM платформы.
и т.д.

1

От VM там одно название. По факту только управление изолятами, сборщик мусора и еще какие то мелочи. А так что сама VM, что дарт код собираются в нативный бинарь и исполняются напрямую AOT компилятором. Полноценная VM с JIT компиляцией используется только для дебага.
Под тем же андроидом приложение компилируется в .so библиотеку, даже не далвик байткод. ред.

1

Давайте разбираться и приходить к правильному общему мнению, не спорю что мы можем ошибаться
1) Kotlin Multiplatform упомянут тут в контексте одного из вариантов шаринга кода между платформами. Да, он не про UI совсем, но все же позволяет например использовать один язык на iOS и Android. 
2) Да, часть VM остается, но внутри скомпилированной в натив (x86 или ARM) библиотеки. https://dev.to/jay_tillu/flutter-compilation-process-41k0
Есть еще какие-то неточности на ваш взгляд?

0

Про флаттер начинают говорить из каждого утюга)
Почему-то не написали про серьезное преимущество - существенно "сократили" жизненный цикл UI-элементов. Во флаттер по сути экран каждый раз перерисовывается заново, это оказалось удобно. Мы в www.xmall.space на основе этой концепции разбили приложение на отдельные модули, которые можно тасовать как хочет клиент. На выходе получаются совершенно разные приложения за короткий срок, которые на нативе делать было бы гораздо сложнее.

1

Согласен, важное преимущество! Не упомянули только потому что пришлось бы вдаваться в технические детали реализации памяти Dart, чтобы объяснить почему это переделки всего UI на каждый кадр (почти) работают так быстро. Можем разобрать в следующей статье

0

Спасибо за статью, автор!
Я использую Flutter для своего проекта под iOS, Android и Web.
За время работы больше всего UI багов заметил на web версии (при большом количестве элементов скролл начинает тормозить). А так есть небольшие придирки к Cupertino элементам, такое ощущение что это китайская копия нативных элементов iOS. Но это лишь мое личное мнение :) да и вообще Material Design достаточно свежо смотрится на iOS.
Вообще платформа нравится. По началу думал использовать в качестве разработки MVP, но теперь думаю что боевой проект тоже можно строить на Flutter!
Всем удачи, коллеги! ред.

1

Web пока еще не стабилен, будем надеяться на скорый полноценный релиз. Зато недавно подключились создатели Ubuntu, а значит Flutter для десктопа начнет развиваться семимильными шагами

0

Хорошая статья. Интересно. Надо бы поближе познакомиться с dart и flutter ред.

1

слушайте, вот вы жалуетесь на язык Dart, а в чём там проблема - в синтаксисе или семантике? ведь можно сделать транспайлер с удобным входным языком типа c#/kotlin/swift/...

0

Отличная идея! Воспользуюсь с удовольствием если кто-то это сделает ;)

0

Спасибо за статьи о flutter! Написал вам в личку везде - получили?

1

Ну как-бы разработчикам очередная экзотическая фигня, которую используют полтора работодателя и Google, не сильно нужна. В тоже время есть React Native, использующий всем привычный и хлебный JavaScript.

0

Да, новизна технологии и язык как раз и вынесены в минусы. Но мы, оценивая качество подхода, ставим ставку на неизбежный рост. Пока статистика подтверждает эту теорию. Если например взять такую субьективную метрику как звездочки на гитхабе, то Flutter уже на 10к обгоняет RN. 
P.S. Ну и еще я хейтер JS ;)

0

По сути  Dart это копия TypeScript только со специфическим синтаксисом, если бы Flutter реализовали на TypeScript как бекенд к C++ , то Flutter развивался бы в несколько раз быстрее. 
В этом случае я бы рекомендовал Microsoft выкинут эт свой тяжелый Xamarin и пойти по пути Flutter 

0

Склонен не согласиться. Да внешне они очень похожи. И зная историю Dart, который появился как замена JS, легко пойти по ошибочному пути.
Главное отличие Dart - он не преобразуется в JS, как TS, а полностью "свое" использует под капотом - свою VM, свою модель памяти и тп. 
Если проводить аналогию, то можно найти похожее в мобильном мире 
Kotlin надстройка над Java, а Swift в стороне, хоть и похож на Kotlin Так же и тут
TypeScript надстройка над JavaScript, а Dart в стороне, хоть и похож на TypeScript

–1

Я имел ввиду архитектурный уровень. Те же промисы, (тот же луп микрозадачь) те же стримы, да строгая типизация, но никаких горутин там. Когда пишешь на Dart  всегда видишь аналогию с TypeScript. И ничего такого что бы его отличало. 

1

Да, все отличия под капотом. Я тоже поначалу недоумевал почему они тот же Kotlin не взяли в качестве языка

0

Интересный объемный материал. Заметил, что еще хорошее погружение в флаттер получается в сравнении с реактом. Например, мне зашел вот этот материал https://tagsoft.co/flutter-vs-react-native/

0
Читать все 20 комментариев
Готовы выбрать победителя премии «Экспортер года eBay — 2021»?
Прошел финал программы скаутинга в киберспорте Winstrike

Итоги программы Winstrike Scouting powered by UltraGear

Как мы проводили командную ретроспективу в Minecraft

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

Почему кейс с хомяком - не ошибка выжившего и не случайность

Сегодня Интернет облетела новость о том, что хомяк, бегая по своей клетке, заработал +29% на крипте. В комментария к публикации на VC многие писали, что это ошибка выжившего и просто случайность, которая ни о чем не значит. Я же постараюсь объяснить, почему это закономерность, и как сделать так, чтобы ваш кот/собака/рыбка показали такой же…

Увидеть первые Apple, сделать копию на ксероксе и потрогать мышку: как в Минске-88 прошла выставка «Информатика в США» Статьи редакции

Выставка стала потрясением для жителей: это было похоже на фильм «Назад в будущее», который на выставке тоже показывали, рассказывает dev.by. Издание поговорило с экс-гидом той выставки и минчанами, которые до сих пор хранят значки с её логотипом.

Ситимобил снял 5547 рублей за поездку в 36 км по городу

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

Нужны ли в России сити-фермы

И появятся ли грядки на крышах пятиэтажек.

re-thinkingthefuture.com
Облажались с аудиторией и производством в Китае, но вышли на 55 млн рублей за 2020 год: история ошибок компании Atmeex

Мы начали производить и продавать приборы по очищению воздуха в конце 2019 года. Первое время всё шло наперекосяк, но мы переосмыслили все процессы и за год увеличили выручку в 2 раза.

В отдельном помещении мы тестируем устройства на брак
Как традиционному малому бизнесу превратиться в стартап: план действий

Сейчас в России предприниматели переходят из традиционного малого бизнеса в стартапы очень редко — меньше чем в 0,02% случаев. Это не больше 1 000 стартапов из около 6 млн предприятий малого бизнеса. Поговорим о том, что мешает предпринимателям и как действовать, если есть желание создать стартап.

Хомяк-криптотрейдер заработал 30% за три месяца в «клетке для торговли» — обойдя Уоррена Баффета и S&P 500 Статьи редакции

Мистер Гокс занимается торговлей криптовалютой с 12 июня.

Как испортить лучшую систему комментариев в рунете на примере vc.ru

Иногда мне кажется, на vc.ru идёт прогресс дизайна ради дизайна, а не ради прогресса. Вот и до комментариев добрались.

null