Как шестая статья в серии, эта статья рассматривает некоторые интересные принципы работы виджетов на основе предыдущих исследований.
Сначала нам следует понять, что такое виджет? Здесь есть «общий знаменатель»: виджеты сами по себе не являются объектами отрисовки. Да, действительно, в Flutter процесс отрисовки проходит через этапы от Widget
до Element
, а затем до RenderObject
.
Мы знаем, что виджеты неизменяемы, но как они строят интерфейсы при этом? Мы уже выяснили, что Widget
должен быть преобразован в Element
для отображения, и из следующего примечания можно заключить, что виджет представляет собой конфигурационное описание для элемента, которое указывает элементу, как его отрисовать.
Какова же взаимосвязь между виджетом и элементом? Из вышеупомянутого примечания также следует, что виджет и элемент имеют отношение один ко многим. В действительности дерево отрисовки состоит из узлов, представляющих экземпляры элементов, а конфигурационные файлы виджетов могут быть переиспользованы в различных частях дерева, создавая множество объектов элемента.А что такое RenderObject
? Как он связан с двумя другими компонентами? Из комментариев в исходном коде можно сделать вывод, что RenderObject
является фактическим объектом отрисовки, а из исходного кода элемента видно, что элемент хранит RenderObject и Widget.
Объединив это с последующей диаграммой, можно сделать вывод, что три компонента имеют следующие отношения: конфигурационный файл Widget создаёт Element, который затем создаёт RenderObject, связывая его с внутренним объектом renderObject
элемента, после чего Flutter использует данные RenderObject для размещения и отрисовки. Теоретически можно сказать, что RenderObject — это конечные данные для отрисовки Flutter, содержащие информацию о размерах и положении, которую Flutter использует для создания изображения.
Рассматривая
RenderObject
, нельзя не упомянуть RenderBox
: «Отрисовочный объект в двумерной декартовой системе координат», из комментариев в исходном коде можно сделать вывод, что он реализует «декартовую систему координат» на основе базовых возможностей размещения и отрисовки, предоставленных RenderObject
: система координат с вершиной и левой стороной в качестве базовых точек, использующая две оси — ширину и высоту — для размещения и вложения. RenderBox избавляет от необходимости непосредственно использовать сложные сценарии с RenderObject
, где размещение и вычисление размера RenderBox
выполняются в методах performLayout()
и performResize()
. Часто мы выбираем наследование RenderBox
для реализации пользовательских компонентов.Учитывая вышеописанное, можно сделать вывод:
widget
) представляет собой конфигурацию данных для отображения и является относительно легковесной единицей. В Flutter есть оптимизация для виджетов, поэтому частое изменение состояния и перестроение виджета обычно не вызывает больших проблем.RenderObject
же отличается тем, что он связан со многими процессами, такими как размещение, вычисление и отрисовку. Полное пересоздание RenderObject
каждый раз может привести к значительному увеличению затрат.Поэтому для каждого изменения требуется проверка того, следует ли создать новый element
и renderObject
, или они могут быть переиспользованы. Например, если тип времени выполнения (runtimeType
) и ключ (key
) нового виджета (newWidget
) совпадают с существующим виджетом (oldWidget
), то используется новый виджет для обновления уже существующего объекта element
. В противном случае создаётся новый объект element
.
Из этого следует, что при пересоздании виджета деревья element
и renderObject
полностью не пересоздаются.
К слову, как мы можем получить размеры и положение размещения?
Для этого нам потребуется ранее упомянутый globalKey
. Через этот ключ мы получаем контекст (buildContext
) контролируемого элемента, а поскольку element
хранит renderObject
, то фактически мы получаем доступ к renderBox
. Таким образом, через renderBox
мы можем получить размеры и положение.```dart
showSizes() {
RenderBox renderBoxRed = fileListKey.currentContext.findRenderObject();
print(renderBoxRed.size);
}
showPositions() { RenderBox renderBoxRed = fileListKey.currentContext.findRenderObject(); print(renderBoxRed.localToGlobal(Offset.zero)); }
---
> Так заканчивается шестая статья! (///▽///)
### Рекомендации по ресурсам
* GitHub: [https://github.com/CarGuo/](https://github.com/CarGuo/)
* **Открытый проект на Flutter: https://github.com/CarGuo/GSYGithubAppFlutter**
* **Множество примеров открытых проектов на Flutter: https://github.com/CarGuo/GSYFlutterDemo**
* **Открытая электронная книга по实战 Flutter: https://github.com/Yöntem CarGuo/GSYFlutterBook**
##### Рекомендация полного открытого проекта* [GSYGithubAppWeex](https://github.com/CarGuo/GSYGithubAppWeex)
* [GSYGithubApp React Native](https://github.com/CarGuo/GSYGithubApp)

Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )