Флаттер не состоит только из виджетов .
Когда вы звоните setState
, вы помечаете виджет как грязный.Но этот виджет на самом деле не то, что вы отображаете на экране.Существуют виджеты для создания / изменения RenderObjects ;это те объекты RenderObject, которые рисуют ваш контент на экране.
Связь между RenderObjects и виджетами осуществляется с помощью нового вида виджетов: RenderObjectWidget (например, LeafRenderObjectWidget )
Большинство виджетов, предоставленных Flutterв некоторой степени являются RenderObjectWidget, включая ListView.
Типичным примером RenderObjectWidget может быть такой:
class MyWidget extends LeafRenderObjectWidget {
final String title;
MyWidget(this.title);
@override
MyRenderObject createRenderObject(BuildContext context) {
return new MyRenderObject()
..title = title;
}
@override
void updateRenderObject(BuildContext context, MyRenderObject renderObject) {
renderObject
..title = title;
}
}
В этом примере используется виджет для создания / обновления RenderObject.Недостаточно сообщить платформе, что есть что перекрасить.
Чтобы перерисовать RenderObject, нужно вызвать markNeedsPaint
или markNeedsLayout
для нужного объекта renderObject.
Обычно это делается самим RenderObject с использованием пользовательского установщика полей следующим образом:
class MyRenderObject extends RenderBox {
String _title;
String get title => _title;
set title(String value) {
if (value != _title) {
markNeedsLayout();
_title = value;
}
}
}
Обратите внимание на if (value != previous)
.
Эта проверка гарантирует, что при перестройке виджетаничего не меняя, Flutter не ретранслирует и не перерисовывает ничего.
Именно из-за этого точного условия мутирование List
или Map
не приводит к повторному отображению ListView
.Он в основном имеет следующее:
List<Widget> _children;
List<Widget> get children => _children;
set children(List<Widget> value) {
if (value != _children) {
markNeedsLayout();
_children = value;
}
}
Но это означает, что если вы измените список вместо создания нового, RenderObject не будет помечен как нуждающийся в пересылке / перерисовке.Поэтому никаких визуальных обновлений не будет.