[Dart, Flutter, Программирование, Разработка мобильных приложений] Flutter под капотом: Binding
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Эта статья прямое продолжение моей предыдущей статьи.
Для полного восприятия советую предварительно ознакомиться с указанной по ссылке статьёй или освежить её в памяти. В ней я разобрал один из важных аспектов устройства Flutter — взаимодействие деревьев и распределение ответственности между ними. Однако, открытым остаётся вопрос: каким образом налажена работа всего механизма, описанного в первой части? В этом мы и постараемся разобраться в этой статье.
Общие положения
Если открыть технический обзор Flutter, в одном из пунктов мы увидим следующую схему. Она показывает условные уровни, на которые сами авторы фреймворка его делят.
По факту, как они сами это и назвали, мы видим слоёный пирог. Можно выделить более крупные и мелкие слои.
Уровень фреймворка — всё, с чем мы работаем в момент написания приложения, и все служебные классы, позволяющие взаимодействовать написанному нами с уровнем движка. Всё, относящееся к данному уровню написано на Dart.
Уровень движка — более низкий уровень, чем уровень фреймворка, содержит классы и библиотеки, позволяющие работать уровню фреймворка. В том числе виртуальная машина Dart, Skia и тд.
Уровень платформы — специфичные механизмы, относящиеся к конкретной платформе запуска.
Рассмотрим подробнее уровень фреймворка. На схеме он изображен в виде слоёв от более высокоуровневого к низкоуровневому. В самом низу мы видим слой Foundation. Исходя из названия, данный слой — нечто фундаментальное и основное на уровне фреймворка. Находим данную библиотеку и вот что написано в её описании:
Core Flutter framework primitives.
The features defined in this library are the lowest-level utility classes and functions used by all the other layers of the Flutter framework.
Функции, определённые в этой библиотеке, представляют собой служебные классы и функции самого низкого уровня, используемые всеми другими уровнями фреймворка Flutter.
В данной библиотеке, в том числе находится BindingBase — базовый класс для всех Binding.
Binding
Для начала давайте разберёмся, что же такое Binding и как он используется во Flutter. Само название говорит нам о том, что это некоторая связь. Документация, оставленная Flutter командой к BaseBinding сообщает нам следующее:
Base class for mixins that provide singleton services (also known as «bindings»). To use this class in an `on` clause of a mixin, inherit from it and implement [initInstances()]. The mixin is guaranteed to only be constructed once in the lifetime of the app (more precisely, it will assert if constructed twice in checked mode).
Это базовый класс для различных сервисов связи, которые представлены в виде миксинов. Каждый такой миксин инициализируется и гарантирует единственность своего экземпляра во время жизни приложения.
BaseBinding — базовый абстрактный класс, давайте тогда рассмотрим конкретные реализации биндингов. Среди них мы увидим:
ServicesBinding отвечает за перенаправление сообщений от текущей платформы в обработчик данных сообщений (BinaryMessenger);
PaintingBinding отвечает за связь с библиотекой отрисовки.
RenderBinding отвечает за связь между деревом рендеринга и движком Flutter.
WidgetBinding отвечает за связь между деревом виджетов и движком Flutter.
SchedulerBinding — планировщик очередных задач, таких как:
- вызовы приходящих колбеков, которые инициирует система в Window.onBeginFrame — например события тикеров и контроллеров анимаций;
- вызовы непрерывных колбеков, которые инициирует система Window.onDrawFrame, например, события для обновления системы отображения после того, как отработают приходящие колбеки;
- посткадровые колбеки, которые вызываются после непрерывных колбеков, перед возвратом из Window.onDrawFrame;
- задачи не связанные с рендерингом, которые должны быть выполнены между кадрами.
SemanticsBinding отвечает за связь слоя семантики и движком Flutter.
GestureBinding отвечает за работу с подсистемой жестов.
Как и следовало из названия, bindings — это прослойка-связь, между уровнем движка Flutter и уровнем самого фреймворка, каждый из которых отвечает за конкретное направление работы.
WidgetsFlutterBinding
Чтобы лучше понять, как всё это работает вместе давайте посмотрим в место, которое является стартовым для любого Flutter приложения — вызов runApp. Метод, который мы вызываем, находится в файле binding.dart и это не случайно. В описании к нему сказано, что он расширяет переданный виджет приложения и прикрепляет его к экрану. Посмотрим, что он делает:
void runApp(Widget app) {
WidgetsFlutterBinding.ensureInitialized()
..scheduleAttachRootWidget(app)
..scheduleWarmUpFrame();
}
Здесь мы встречаем WidgetsFlutterBinding — конкретная реализация привязки приложений на основе инфраструктуры виджетов. По сути своей — это клей, соединяющий фреймворк и движок Flutter. WidgetsFlutterBinding состоит из множества связей, рассмотренных нами ранее: GestureBinding, ServicesBinding, SchedulerBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding. Таким образом мы получили прослойку, которая умеет связывать наше приложение по всем нужным направлениям с движком Flutter.
Вернёмся к запуску приложения. У WidgetsFlutterBinding вызываются методы scheduleAttachRootWidget и scheduleWarmUpFrame, рассмотрим что в них происходит.
ScheduleAttachRootWidget
Метод scheduleAttachRootWidget является отложенной реализацией attachRootWidget. Принадлежит данный метод WidgetsBinding. В описании к нему сказано, что он присоединяет переданный виджет к renderViewElement — корневому элементу дерева элементов.
void attachRootWidget(Widget rootWidget) {
_renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
container: renderView,
debugShortDescription: '[root]',
child: rootWidget,
).attachToRenderTree(buildOwner, renderViewElement);
}
По коду мы видим, что в этом методе создаётся адаптер RenderObjectToWidgetAdapter, который является корневым виджетом дерева виджетов и используется как мост, связывающий деревья между собой. Посмотрев в его реализацию, увидим, что он не создаёт RenderObject для себя, а возвращает значение из поля container, а в него мы при создании передаём renderView из RendererBinding. Данный renderView и есть корневой элемент дерева рендеринга.
RenderView get renderView => _pipelineOwner.rootNode;
PipelineOwner фактически является менеджером, который занимается управлением процесса рендеринга.
Вернёмся к методу attachRootWidget. У созданного адаптера вызывается метод attachToRenderTree, с помощью которого мы создаём первый раз корень дерева элементов. Стоит обратить внимание, что в метод attachToRenderTree передаётся buildOwner. Это класс менеджер билда дерева виджетов, который занимается отслеживанием состояния виджетов, отслеживает необходимость обновления и выполняет ряд других важных задач, связанных с актуализацией состояния дерева виджетов. Таким образом мы и получаем те самые три дерева Flutter, каждое из которых хранится и управляется через Bindings.
ScheduleWarmUpFrame
Метод scheduleWarmUpFrame принадлежит SchedulerBinding и используется для того, чтобы запланировать запуск кадра как можно скорее, не ожидая системного сигнала «Vsync». Поскольку метод используется во время запуска приложения, первый кадр, который, вероятно, будет довольно дорогим, будет запущен за некоторое дополнительное время. Данный метод блокирует отправку событий до завершения запланированного кадра.
Как мы видим, оба запущенных при старте механизма относятся и взаимодействуют с различными Bindings, которые в свою очередь тесно связаны и обеспечивают взаимодействие с системой. Давайте подытожим с помощью следующей диаграммы.
Заключение
Bindings — это важный механизм организации работы приложения на Flutter. Именно он связывает различные аспекты работы приложения между собой, а также с движком.
В том числе благодаря ему мы можем писать наше приложение на самой высокоуровневой части фреймворка, не заботясь о том, как же нам организовать связную работу всего остального. Надеюсь данная статья поможет вам разобраться с этой частью устройства Flutter.
Спасибо за внимание!
Используемые материалы:
Flutter
https://flutter.dev/
===========
Источник:
habr.com
===========
Похожие новости:
- [Программирование, GitHub, Управление разработкой, Удалённая работа] «Конституция» для разработчиков: как страничка на GitHub помогает нам не ругаться уже год
- [C, Java, Python, Исследования и прогнозы в IT, Программирование] IEEE опубликовал новый рейтинг языков программирования
- [Java, Разработка мобильных приложений, Разработка под Android] Как подружить RxJava с VIPER в Android, подходы применения и о структуре планировщиков
- [.NET, C#, Программирование, Совершенный код] Медленный код, зато красивый — вообще не проблема, пока ты знаешь, как его ускорить
- [DevOps, Программирование] DevOps-инструменты, которые должен изучить каждый в 2020 году (перевод)
- [JavaScript, VueJS, Программирование, Расширения для браузеров] Пишем свой плагин для VueJS. Как проект на VueJS трансформировать в расширение для браузера?
- [Машинное обучение, Программирование] Нейронки «с нуля», или Как мы делали помощника для наших диспетчеров техподдержки
- [Java, Программирование] Small things that pollute your code
- [ReactJS, Лайфхаки для гиков, Облачные сервисы, Программирование] 10 инструментов для повышения продуктивности React-девелоперов в 2020 году (перевод)
- [C++, Научно-популярное, Программирование] Дядя Миша. Основы организации оперативной памяти и работа с ней в С\С++
Теги для поиска: #_dart, #_flutter, #_programmirovanie (Программирование), #_razrabotka_mobilnyh_prilozhenij (Разработка мобильных приложений), #_surf, #_flutter, #_razrabotka_mobilnyh_prilozhenij (разработка мобильных приложений), #_razrabotka_pod_ios_i_android (разработка под ios и android), #_blog_kompanii_surf (
Блог компании Surf
), #_dart, #_flutter, #_programmirovanie (
Программирование
), #_razrabotka_mobilnyh_prilozhenij (
Разработка мобильных приложений
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 23-Ноя 03:58
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Эта статья прямое продолжение моей предыдущей статьи. Для полного восприятия советую предварительно ознакомиться с указанной по ссылке статьёй или освежить её в памяти. В ней я разобрал один из важных аспектов устройства Flutter — взаимодействие деревьев и распределение ответственности между ними. Однако, открытым остаётся вопрос: каким образом налажена работа всего механизма, описанного в первой части? В этом мы и постараемся разобраться в этой статье. Общие положения Если открыть технический обзор Flutter, в одном из пунктов мы увидим следующую схему. Она показывает условные уровни, на которые сами авторы фреймворка его делят. По факту, как они сами это и назвали, мы видим слоёный пирог. Можно выделить более крупные и мелкие слои. Уровень фреймворка — всё, с чем мы работаем в момент написания приложения, и все служебные классы, позволяющие взаимодействовать написанному нами с уровнем движка. Всё, относящееся к данному уровню написано на Dart. Уровень движка — более низкий уровень, чем уровень фреймворка, содержит классы и библиотеки, позволяющие работать уровню фреймворка. В том числе виртуальная машина Dart, Skia и тд. Уровень платформы — специфичные механизмы, относящиеся к конкретной платформе запуска. Рассмотрим подробнее уровень фреймворка. На схеме он изображен в виде слоёв от более высокоуровневого к низкоуровневому. В самом низу мы видим слой Foundation. Исходя из названия, данный слой — нечто фундаментальное и основное на уровне фреймворка. Находим данную библиотеку и вот что написано в её описании: Core Flutter framework primitives. The features defined in this library are the lowest-level utility classes and functions used by all the other layers of the Flutter framework. Функции, определённые в этой библиотеке, представляют собой служебные классы и функции самого низкого уровня, используемые всеми другими уровнями фреймворка Flutter. В данной библиотеке, в том числе находится BindingBase — базовый класс для всех Binding. Binding Для начала давайте разберёмся, что же такое Binding и как он используется во Flutter. Само название говорит нам о том, что это некоторая связь. Документация, оставленная Flutter командой к BaseBinding сообщает нам следующее: Base class for mixins that provide singleton services (also known as «bindings»). To use this class in an `on` clause of a mixin, inherit from it and implement [initInstances()]. The mixin is guaranteed to only be constructed once in the lifetime of the app (more precisely, it will assert if constructed twice in checked mode). Это базовый класс для различных сервисов связи, которые представлены в виде миксинов. Каждый такой миксин инициализируется и гарантирует единственность своего экземпляра во время жизни приложения. BaseBinding — базовый абстрактный класс, давайте тогда рассмотрим конкретные реализации биндингов. Среди них мы увидим: ServicesBinding отвечает за перенаправление сообщений от текущей платформы в обработчик данных сообщений (BinaryMessenger); PaintingBinding отвечает за связь с библиотекой отрисовки. RenderBinding отвечает за связь между деревом рендеринга и движком Flutter. WidgetBinding отвечает за связь между деревом виджетов и движком Flutter. SchedulerBinding — планировщик очередных задач, таких как:
SemanticsBinding отвечает за связь слоя семантики и движком Flutter. GestureBinding отвечает за работу с подсистемой жестов. Как и следовало из названия, bindings — это прослойка-связь, между уровнем движка Flutter и уровнем самого фреймворка, каждый из которых отвечает за конкретное направление работы. WidgetsFlutterBinding Чтобы лучше понять, как всё это работает вместе давайте посмотрим в место, которое является стартовым для любого Flutter приложения — вызов runApp. Метод, который мы вызываем, находится в файле binding.dart и это не случайно. В описании к нему сказано, что он расширяет переданный виджет приложения и прикрепляет его к экрану. Посмотрим, что он делает: void runApp(Widget app) {
WidgetsFlutterBinding.ensureInitialized() ..scheduleAttachRootWidget(app) ..scheduleWarmUpFrame(); } Здесь мы встречаем WidgetsFlutterBinding — конкретная реализация привязки приложений на основе инфраструктуры виджетов. По сути своей — это клей, соединяющий фреймворк и движок Flutter. WidgetsFlutterBinding состоит из множества связей, рассмотренных нами ранее: GestureBinding, ServicesBinding, SchedulerBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding. Таким образом мы получили прослойку, которая умеет связывать наше приложение по всем нужным направлениям с движком Flutter. Вернёмся к запуску приложения. У WidgetsFlutterBinding вызываются методы scheduleAttachRootWidget и scheduleWarmUpFrame, рассмотрим что в них происходит. ScheduleAttachRootWidget Метод scheduleAttachRootWidget является отложенной реализацией attachRootWidget. Принадлежит данный метод WidgetsBinding. В описании к нему сказано, что он присоединяет переданный виджет к renderViewElement — корневому элементу дерева элементов. void attachRootWidget(Widget rootWidget) {
_renderViewElement = RenderObjectToWidgetAdapter<RenderBox>( container: renderView, debugShortDescription: '[root]', child: rootWidget, ).attachToRenderTree(buildOwner, renderViewElement); } По коду мы видим, что в этом методе создаётся адаптер RenderObjectToWidgetAdapter, который является корневым виджетом дерева виджетов и используется как мост, связывающий деревья между собой. Посмотрев в его реализацию, увидим, что он не создаёт RenderObject для себя, а возвращает значение из поля container, а в него мы при создании передаём renderView из RendererBinding. Данный renderView и есть корневой элемент дерева рендеринга. RenderView get renderView => _pipelineOwner.rootNode; PipelineOwner фактически является менеджером, который занимается управлением процесса рендеринга. Вернёмся к методу attachRootWidget. У созданного адаптера вызывается метод attachToRenderTree, с помощью которого мы создаём первый раз корень дерева элементов. Стоит обратить внимание, что в метод attachToRenderTree передаётся buildOwner. Это класс менеджер билда дерева виджетов, который занимается отслеживанием состояния виджетов, отслеживает необходимость обновления и выполняет ряд других важных задач, связанных с актуализацией состояния дерева виджетов. Таким образом мы и получаем те самые три дерева Flutter, каждое из которых хранится и управляется через Bindings. ScheduleWarmUpFrame Метод scheduleWarmUpFrame принадлежит SchedulerBinding и используется для того, чтобы запланировать запуск кадра как можно скорее, не ожидая системного сигнала «Vsync». Поскольку метод используется во время запуска приложения, первый кадр, который, вероятно, будет довольно дорогим, будет запущен за некоторое дополнительное время. Данный метод блокирует отправку событий до завершения запланированного кадра. Как мы видим, оба запущенных при старте механизма относятся и взаимодействуют с различными Bindings, которые в свою очередь тесно связаны и обеспечивают взаимодействие с системой. Давайте подытожим с помощью следующей диаграммы. Заключение Bindings — это важный механизм организации работы приложения на Flutter. Именно он связывает различные аспекты работы приложения между собой, а также с движком. В том числе благодаря ему мы можем писать наше приложение на самой высокоуровневой части фреймворка, не заботясь о том, как же нам организовать связную работу всего остального. Надеюсь данная статья поможет вам разобраться с этой частью устройства Flutter. Спасибо за внимание! Используемые материалы: Flutter https://flutter.dev/ =========== Источник: habr.com =========== Похожие новости:
Блог компании Surf ), #_dart, #_flutter, #_programmirovanie ( Программирование ), #_razrabotka_mobilnyh_prilozhenij ( Разработка мобильных приложений ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 23-Ноя 03:58
Часовой пояс: UTC + 5