Привет всем, меня зовут Гуо Шу Юнь, автор книги "Практическое руководство по разработке приложений с использованием Flutter" и ответственный за открытое программное обеспечение серии проектов GSY на GitHub. В настоящее время моя открытая версия gsy_github_app_flutter имеет более 13 000 звёзд и занимает первое место в общем рейтинге Dart среди китайских проектов.
Данные взяты из: https://github.com/GrowingGit/GitHub-Chinese-Top-Charts/blob/master/content/charts/overall/software/Dart.md
С момента как Flutter был открыт, прошло уже почти семь лет. Я начал работать с Flutter в 2017 году, а сегодня, в 2022 году, можно сказать, что Flutter больше не является малочисленной платформой для кросс-разработки.
Как показано на следующей диаграмме, сейчас у Flutter более 135 000 звёзд, более 10 000 открытых и более 50 000 закрытых запросов на исправление ошибок, что свидетельствует о высокой активности сообщества и пользователей.
По данным исследования, проведённого во второй половине прошлого года, Flutter занял первое место среди наиболее используемых и любимых кросс-платформ для разработки. Это заявление не означает, что вы обязательно должны учиться Flutter, но говорит о том, что независимо от того, нравится вам это или нет, Flutter уже доказал свою ценность.
Данные взяты из: https://rvtechnologies.com/10-reasons-why-flutter-is-growing-as-a-cross-platform-framework/
На самом деле, за последние два года я провёл некоторые простые исследования:
Эта выборка данных довольно мала, основана на моих личных предпочтениях и поэтому недостоверна и не представительна, но она может частично отражать текущее использование Flutter в Китае.
Данные взяты из: https://juejin.cn/post/7012382656578977806
Наконец, Flutter также поддерживает работу на веб-страницах и ПК, хотя я пока не внёс его в производственные процессы. Можно сделать вывод, что:
HtmlCanvas
и CanvasKit
(WASM). По умолчанию мобильные устройства используют HTML, а настольные — WASM;Дополнительные материалы: https://juejin.cn/post/7059619009213726733
Electron
. Можно сказать, что версия Flutter для ПК может использовать меньше памяти и иметь меньший размер, а также лучше поддерживать FFI (Foreign Function Interface) для работы с C. Однако экосистема пока слабее, поддержка сторонних разработчиков ограничена, поэтому вам придётся решать больше вопросов самостоятельно.> Официальная версия для Windows уже выпущенаДополнительные материалы: https://juejin.cn/post/7018450473292136456
Как кросс-платформенный фреймворк для создания графического интерфейса, Flutter имеет основное преимущество в том, чтобы обеспечить независимость UI от платформы при приемлемой производительности, то есть с точки зрения платформы, Flutter представляет собой "одностраничное" приложение.
Что такое "одностраничное" приложение?
Для нативных Android и iOS это значит, что вся кросс-платформенная UI по умолчанию работает внутри одного Activity
/ ViewController
, по умолчанию существует только один Activity
/ ViewController
. Таким образом, Flutter, React Native, Weex и Ionic по умолчанию работают таким образом, поэтому маршруты фреймворков обычно не связаны напрямую с маршрутами нативных приложений.
Например, рассмотрим следующий пример:
FlutterA
и FlutterB
;Activity
/ ViewController
, запускается нативная страница X, которая затем добавляется в стек маршрутов нативного уровня, тем самым скрывая FlutterActivity
/ FlutterViewController
, то есть скрывая FlutterA
и FlutterB
;FlutterC
в стеке маршрутов Flutter, она также будет скрыта за счет нативной страницы X.Поэтому можно заключить, что по умолчанию кросс-платформенные приложения являются одностраничными, и их стек маршрутов несовместим с маршрутом нативного уровня.
Конечно, слово "по умолчанию" используется дважды, так как действительно возможно создание пользовательских смешанных стеков маршрутов, таких как официальный
FlutterEngineGroup
, сторонние фреймворкиflutter_boost
,mix_stack
,flutter_thrio
и т.д., все они предназначены для решения задач смешанной разработки.
После рассмотрения различий в части "одностраничной" архитектуры, давайте поговорим о различных подходах Flutter к рендерингу.
На уровне рендера Flutter значительно отличается от других кросс-платформенных фреймворков. Ниже приведена схема сравнения текущих популярных моделей рендера:
Для нативного Android используется нативный код, который проходит через Skia и затем до GPU для окончательного рендера. Нативная система Android уже включает в себя библиотеку Skia;
Для Flutter контроллеры Dart кода проходят через Skia и затем до GPU для окончательного рендера, где на Android используется системная версия Skia, а на iOS — версия, которая встроена в проект;- Для проектов типа ReactNative/Weex код выполняется внутри соответствующего движка JavaScript, после чего он преобразуется в нативные контроллеры и использует возможности рендера этих контроллеров; (ПС: В этом году официальная версия наконец выпустит переоформленную версию: Новый архитектурный обзор React Native 2022 года)- Для кросс-платформенных фреймворков типа Ionic используются преимущественно возможности рендера WebView.
На Android Skia может использовать либо OpenGL, либо Vulkan, в зависимости от ситуации, а на iOS если есть поддержка Metal, то она будет использоваться для ускоренного рендера.
Из вышеописанного можно сделать вывод:
ReactNative/Weex
и подобные кросс-платформенные решения имеют значительную связь с нативными платформами:
Преимущество заключается в том, что использование нативных контроллеров требует меньших затрат на интеграцию;
Однако недостаток состоит в том, что рендеринг сильно зависит от возможностей нативных контроллеров, что увеличивает степень耦合,并增加了后期开发过程中的维护成本。
Например: в iOS хорошо отладленные стили при переходе на Android могут вызвать ошибки; эффективные стили на Android могут не поддерживаться на iOS; эффекты контролов на iOS могут отличаться от эффектов на Android, например, при выполнении операций pull-to-refresh и AppBar. Если добавить мелкие различия между версиями каждого системы, проблема становится еще более сложной.
Например, различия в эффектах тени на Android и iOS.
Flutter
отличается тем, что использует прямое взаимодействие с Skia и GPU, обеспечивая платформо-независимость контролов на Android и iOS. Другими словами, большинство Widgets
в Flutter
являются независимыми от Android и iOS. Основной принцип работы нативной платформы заключается в предоставлении аналогичного объекта Surface
, после чего отрисовка соответствующих компонентов осуществляется с помощью Flutter.> Обычно используется объект FlutterView
как контейнер для отрисовки; на Android он может использовать внутренние реализации таких классов, как SurfaceView
, TextureView
или FlutterImageView
; а на iOS — это UIView
, использующий слои (layers
) для отрисовки.Поэтому компоненты Flutter могут обеспечивать единый внешний вид на различных платформах, но смешивание их с нативными компонентами требует значительных усилий и затрат, что связано с возможностью использования нативных компонентов через механизм PlatformView
. Реализация PlatformView
сама по себе может вызывать проблемы с памятью и клавиатурой, поэтому её внедрение также является дорогостоящим процессом.
В последних версиях системы настоятельно рекомендовано использование Hybrid Composition, что делает его немного лучше по сравнению с ранними версиями
PlatformView
, хотя некоторые проблемы всё ещё остаются. Например, проблема смены клавиатуры при вводе пароля или мерцание экрана при переходе между страницами.
Как показано на приведённой выше 图为所示,默认情况下 Flutter 工程结构是这样的:
android
是原生项目的目录,可以在此处配置应用程序名(appName
)、图标(logo
)、启动画面以及 AndroidManifest.xml
等;ios
是 iOS 项目的目录,在这里可以配置启动画面、图标、应用名称及 Info.plist
文件等;build
目录是在编译过程中生成的,通常被 Git 忽略,打包过程及其输出结果均存放于此;lib
目录用于编写 Dart 代码,主程序入口通常是 main.dart
;pubspec.yaml
文件是 Flutter 工程中非常重要的文件之一,无论是静态资源引用(例如图片、字体)、第三方库依赖还是 Dart 版本声明都会记录在此文件内。如下图是对 pubspec.yaml
文件结构的说明
Поэтому компоненты Flutter могут обеспечивать единый внешний вид на различных платформах, но смешивание их с нативными компонентами требует значительных усилий и затрат, что связано с возможностью использования нативных компонентов через механизм PlatformView
. Реализация PlatformView
сама по себе может вызывать проблемы с памятью и клавиатурой, поэтому её внедрение также является дорогостоящим процессом.
В последних версиях системы настоятельно рекомендовано использование Hybrid Composition, что делает его немного лучше по сравнению с ранними версиями
PlatformView
, хотя некоторые проблемы всё ещё остаются. Например, проблема смены клавиатуры при вводе пароля или мерцание экрана при переходе между страницами.
Как показано на приведённой выше иллюстрации, по умолчанию структура проекта Flutter выглядит следующим образом:
android
— директория для native проекта, где можно задать имя приложения (appName
), логотип (logo
), splash screen и файл AndroidManifest.xml
.ios
— директория для iOS проекта, где можно задать splash screen, логотип, название приложения и файл Info.plist
.build
— директория, которая создаётся во время сборки, обычно игнорируется Git, здесь хранятся результаты сборки и её выходные данные.lib
— директория для написания кода на Dart, главный входной файл программы обычно называется main.dart
.pubspec.yaml
— важнейший файл проекта Flutter, который содержит информацию о зависимостях библиотек, статических ресурсах (например, изображения, шрифты) и версии Dart.Следующий рисунок демонстрирует структуру файла pubspec.yaml
:
Обратите внимание, что при изменении этого файла необходимо выполнить команду
flutter pub get
и остановить текущее приложение перед перезапуском всего проекта. Одновременно использовать функцию горячей перезагрузки невозможно.
Далее представлен пример структуры Flutter плагина. Flutter делится на типы Package
и Plugin
,
Package
, то это чистый Flutter пакет, который не содержит никакого кода на нативном языке;Plugin
, то это Flutter плагин, который включает код для платформ Android и iOS.Перед запуском Flutter необходимо выполнить команду flutter pub get
, чтобы синхронизировать и скачать сторонние зависимости. Сторонние зависимости обычно хранятся в директории (Mac
) /Users/ваш_имя_пользователя/.pub-cache
.
После успешной загрузки зависимостей можно запустить проект Flutter через команду flutter run
или нажав кнопку "Run" в среде разработки (IDE). Этот процесс требует выполнения некоторых сетевых операций в нативных проектах, таких как:
pod install
для синхронизации зависимостей на платформе iOS;Если требуется следить за прогрессом синхронизации:
./gradlew assembleDebug
в директории android/
;pod install
в директории ios/
.Среди синхронизируемых плагинов, если это Plugin
с логикой на native платформе, то в корневой директории проекта будут находиться файлы .flutter_plugins
и .flutter-plugins-dependencies
. Эти файлы игнорируются системой контроля версий (git) и используются для указания местоположения плагинов на локальной машине. При запуске Flutter эти пути используются для динамического добавления зависимостей.По умолчанию Flutter работает в режиме JIT при запуске в debug, что делает его менее производительным, но позволяет использовать hot-reload.
В режиме release используется AOT компиляция, что значительно увеличивает скорость работы. Кроме того, Flutter по умолчанию использует CPU для запуска на эмуляторах и GPU для запуска на реальных устройствах, поэтому производительность также различается.
Внимание: на реальном устройстве iOS 14 запуск в режиме debug после отключения соединения невозможен повторить.
Если проект сталкивается с проблемами кэширования, можно очистить кэш, выполнив команду flutter clean
.
И последнее, почему Flutter не поддерживает горячую загрузку?
Ранее было упомянуто, что ReactNative и Weex используют JavaScript для преобразования UI-компонентов в native компоненты, а значит, что сама часть кода на JavaScript является просто текстом. Отправка этого текста через code-push
не нарушает требование платформы.
В случае Flutter, скомпилированные файлы являются двоичными, и отправка этих двоичных файлов явно противоречит требованиям платформы.> После сборки в режиме release Android генерирует два динамических библиотеки: libapp.so
и libflutter.so
; iOS создает два файла: App.framework
и Flutter.framework
. Поэтому сторонние решения для горячего обновления Flutter включают такие как: MXFlutter
, Fair
, Kraken
, LiteApp
, NEJFlutter
, Flap
(MTFlutter), flutter_code_push
(Chimera) и так далее. Однако эти фреймворки не отправляют исполняемые двоичные файлы напрямую. На рынке можно выделить две основные категории решений для динамизации в зависимости от различий в DSL (Domain Specific Language): ориентированные на фронтенд и ориентированные на конечное устройство.На следующей схеме показаны примеры таких решений, как LiteApp
компании WXG, MxFlutter
компании Tencent и Kraken
компании Alibaba (Бэйхай), которые ориентированы на фронтенд и используют JavaScript/TypeScript.
На следующей схеме представлены примеры таких решений, как Flap
и flutter_code_push
, которые ориентированы на конечное устройство и требуют работы над DSL или кодом на Dart.
Ссылка: https://tech.meituan.com/2020/06/23/meituan-flutter-flap.html
Наконец, относительно поддержки динамического обновления Flutter, можно обратиться к следующей таблице:
Ссылка: Flutter реализует динамическое обновление — технический анализ
Здесь мы рассмотрим некоторые аспекты Flutter, связанные с Dart, особенно для нативной разработки следует прежде всего понять концепцию реактивного программирования и Widget
.
Реактивное программирование также известно как декларативное программирование, что является основой современной фронтенд-разработки. Это также тренд в области клиентской разработки, такой как Jetpack Compose
и SwiftUI
.
**Jetpack Compose и Flutter имеют очень похожие характеристики на поверхности.**Основная идея реактивного программирования заключается в том, чтобы не выполнять обновление интерфейса вручную, а просто "объявить" его через код, установить связи между данными и интерфейсом, и при обновлении данных интерфейс будет автоматически обновлен.
Из точки зрения кода, для нативной разработки нет необходимости использовать XML для создания макетов или storyboard. Макет полностью создается с помощью кода, то есть "что видишь, то и получаешь". Также нет необходимости работать с объектами интерфейса для присваивания значений или обновления; все, что требуется, это настройка отношений между данными и интерфейсом.
Основное отличие реактивного программирования от методов данных-биндинга или MVVM состоит в том, что каждый раз он заново строит и корректирует всю деревянную структуру отрисовки, а не просто выполняет операцию видимости для UI. Вот ниже приведён пример третьей стороны для адаптивного интерфейса в Flutter:
responsive_framework
.
Widget
— это базовый концепт в Flutter, с которым мы работаем напрямую при написании кода. **Внутри Flutter всё является виджетом, виджеты являются неизменяемыми (immutable), каждый виджет представляет состояние одной кадровой фреймы.**Поэтому Widget
, как объект immutable
, не может являться настоящим объектом пользовательского интерфейса. Настоящие объекты уровня View
в Flutter — это Element
и RenderObject
. Абстракция Element
— это часто используемый нами BuildContext
.
Пример: в следующем коде Text
виджет testUseAll
используется трижды на одном экране, и код корректно отображается. Если бы это был настоящий View
, он не смог бы использоваться одновременно несколькими местами на одном экране.
Итак, в Flutter виджеты выполняют роль конфигурационных файлов, они используются для описания конфигураций интерфейсов. Подробнее о реализациях логики, отношений и типов виджетов можно прочитать в третьей и четвертой главах моей книги «Flutter: Разработка и практические примеры».
Заключение: один интересный вопрос. Некоторые люди спрашивают, передаются ли значения или ссылки в Flutter? На этот вопрос есть множество путаницы в интернете, но ответ очень прост:
Все в Flutter — это объекты, даже такие примитивные типы данных, как int
, double
, bool
, тоже являются объектами. Как вы думаете, что передаются при работе с объектами?
Однако операции над объектами могут различаться. Например, операции сложения, вычитания, умножения и деления для классов int
и double
вызывают методы операторов этих классов, а затем возвращают объект типа num
.
Для понимания того, что происходит внутри этих операций, достаточно взглянуть на то, что делает объект Double
при выполнении операций сложения, вычитания, умножения и деления. Вот пример такого поведения:
И последнее, поговорим немного о Flutter и Compose.
С момента появления Jetpack Compose вопрос выбора между Flutter и Compose начал возникать в Android-разработке, как это было ранее с iOS-разработчиками, выбирающими между Flutter и SwiftUI. Для Android-разработчиков этот выбор может быть "более болезненным", так как Flutter и Compose имеют общего "отца".
Здесь я предоставляю лишь своё личное понимание и не претендую на официальную точку зрения:
Цели будущего развития Flutter и Compose будут довольно схожими, но их первоначальные цели были различными.
Сначала, Compose является новой UI-библиотекой серии Jetpack, осознайте это! Compose — это часть серии Jetpack, поэтому его можно использовать для разработки пользовательского интерфейса Android, поэтому вы можете выбрать не использовать его, но вы всё равно сможете разрабатывать пользовательский интерфейс Android.Затем рассмотрим цель создания Compose: он был создан для того, чтобы переопределить способ написания пользовательских интерфейсов на Android, чтобы повысить эффективность разработки нативных пользовательских интерфейсов Android и сделать методы разработки пользовательских интерфейсов Android актуальными для современной эпохи.> Нравится вам это или нет, декларативное программирование пользовательских интерфейсов стало трендом сегодняшнего дня, что демонстрируют такие технологии, как React, SwiftUI и Flutter.
Что же касается Flutter, то его ключевой особенностью является возможность работы на нескольких платформах, поскольку Flutter сам по себе не имеет своей собственной платформы. Некоторые говорят, что Fuchsia станет домом для Flutter, но это уже другая история, ведь Fuchsia должна сначала стать жизнеспособной.
Flutter был создан как новый UI-фреймворк для работы на нескольких платформах, от нижних уровней до верхних — всё это представляет собой смелые и инновационные решения, а использование языка Dart само по себе является очень смелым решением. Даже на веб-платформе Flutter использует WASM-модель CanvasKit.
Поэтому "вольность" Flutter с самого начала вызывала вопросы, и даже сейчас есть те, кто её не одобряет, потому что она в какой-то степени экстремальна и не всегда удобна.
Кроме того, с точки зрения происхождения и поддержки:
Поэтому они происходят и поддерживаются разными группами, поэтому со стороны может показаться, что могут быть конфликты ресурсов, но на самом деле они являются разными большими группами, поддерживающими эти проекты.Ну вот, многословие закончилось, давайте сделаем вывод:
Стоит отметить, что эти библиотеки всё ещё сосредоточены на создании UI, поэтому выбор зависит от ваших предпочтений. Конечно, возможно, что важнее всего будет требование вашего руководителя.
По поводу конфликта между Flutter и Compose:
Из точки зрения проекта, Flutter и Compose могут казаться конкурирующими, но с точки зрения пользователя они не конкурируют.
Потому что для разработчика неважно, начнёт ли он учиться Compose или Flutter первым — каждый из этих навыков поможет ему освоить другой. Умение использовать один из них автоматически увеличивает шансы на успешное использование другого примерно до 70%.С точки зрения будущего:
Если вы работаете с нативными приложениями и ещё не столкнулись с Flutter, лучше начните с Compose, это будет полезно для вашей карьеры Android-разработчика, а затем переход к Flutter будет легче.
Если вы уже используете или изучаете Flutter, продолжайте развиваться, не стоит прекращать обучение из-за страха перед Compose. Когда вы освоите Flutter, вы окажетесь недалеко от понимания Compose.
Будущее обоих заключается в многоплатформенной разработке, а конфликт между ними больше связан с процессом обучения, чем с выбором одной из них.
С практической точки зрения: в настоящее время Android и iOS под Flutter 2.0 становятся всё более стабильными, Web-версия достигла стабильной ветки, а MacOS/Linux/Windows находятся в стадии бета-тестирования и доступны для просмотра через стабильную версию. Поэтому если вам требуется многоплатформенная разработка, включая ПК, Flutter является лучшим выбором.
Выбор React Native тоже возможен, кстати, последняя версия React Native — OnClickListener, которая всё ещё не достигла версии 1.0...Конечно, многие будут интересоваться тем, есть ли какие-либо проблемы с этими фреймворками. Основная проблема всех фреймворков заключается в том, что они имеют свои сложности; даже сетевые факторы могут стать вашими болевыми точками. Вопрос в том, готовы ли вы принять эти трудности, поскольку работа за кулисами любой платформы всегда связана с "грязной" работой. Путь Flutter к многоплатформенной разработке был сложным, и достижение стабильности на Android и iOS уже было большим шагом.Наконец, следует отметить следующий момент:
Многоплатформенная разработка существует благодаря наличию соответствующих нативных платформ, многие проблемы нативных платформ требуют решения именно на этих платформах. Те, кто говорит о том, что Flutter или React Native доминируют и унифицируют все методы и платформы, должны понимать различия между этими методами и платформами и учиться больше для этого.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )