fix more than needed rebuilds on canvas children

this used a stupid builderFunc instead of a widget so flutter wasn't able to optimise those widget builds and it was simply a blanket rebuild. Added more examples as well
This commit is contained in:
2025-07-26 17:47:42 +00:00
parent 96e55a7157
commit 7ad54a92cb
8 changed files with 427 additions and 12 deletions
+18 -5
View File
@@ -77,9 +77,9 @@ class LazyCanvasController with ChangeNotifier {
// ==================== Child Management ====================
/// Add a child at a given position with a builder. Returns the child ID.
int addChild(Offset position, WidgetBuilder builder) {
_children[_nextId] = _ChildInfo(gsPosition: position, builder: builder);
/// Add a child at a given position with a widget. Returns the child ID.
int addChild(Offset position, Widget widget) {
_children[_nextId] = _ChildInfo(gsPosition: position, widget: widget);
_spatialHash.add(position.toPoint(), _nextId); // add to spatial hash
notifyListeners();
return _nextId++;
@@ -117,6 +117,19 @@ class LazyCanvasController with ChangeNotifier {
}
}
/// Update a child's widget.
void updateChildWidget(int id, Widget newWidget) {
if (_children.containsKey(id)) {
final child = _children[id]!;
// Create a new _ChildInfo with the new widget
_children[id] = _ChildInfo(gsPosition: child.gsPosition, widget: newWidget)
..lastRenderedSize = child.lastRenderedSize;
notifyListeners();
} else {
throw _ChildNotFoundException;
}
}
/// Get the position of a child by its ID.
Offset getPosition(int id) {
if (_children.containsKey(id)) {
@@ -183,7 +196,7 @@ class LazyCanvasController with ChangeNotifier {
return _renderedChildrenCache = idsToBuild.map((id) {
final item = _children[id]!;
final ssPosition = gsToSs(item.gsPosition, _gsTopLeftOffset, _scale);
var child = item.builder(context);
var child = item.widget;
if (debug) child = _Debug(id: id, gs: item.gsPosition, ss: ssPosition, child: child);
return ChildInfo(id: id, gsPosition: item.gsPosition, ssPosition: ssPosition, child: child);
}).toList();
@@ -237,7 +250,7 @@ class LazyCanvasController with ChangeNotifier {
// else do an offstage render
childSize ??= childInfo.lastRenderedSize != null && !forceRedraw
? childInfo.lastRenderedSize
: measureWidgetSize(context, childInfo.builder);
: measureWidgetSize(context, (_) => childInfo.widget);
/*
margin is symmatric on ltrb so
+2 -2
View File
@@ -9,9 +9,9 @@ final _ChildNotFoundException = Exception('Child with the given ID does not exis
class _ChildInfo {
Offset gsPosition;
Size? lastRenderedSize;
final WidgetBuilder builder;
final Widget widget;
_ChildInfo({required this.gsPosition, required this.builder});
_ChildInfo({required this.gsPosition, required this.widget});
}
class ChildInfo {