Stocks has both tabs reified in the wiget tree

We were recomputing which widgets to show only when we were on the other side
of the repaint boundaries. That doesn't work well for pageable lists because we
come to rest exactly on a repaint boundary, which means we don't cull the other
page.

After this patch, we recompute the set of widgets using an edge-trigger when we
hit the boundary. That's better than using a level-trigger so that we don't
continuously recompute the set of widget as we sit at the boundary.
This commit is contained in:
Adam Barth 2016-01-14 10:19:05 -08:00
parent 1c292d68d9
commit b5ed355b93
4 changed files with 26 additions and 12 deletions

View File

@ -225,10 +225,10 @@ class _PageViewportElement extends VirtualViewportElement<PageViewport> {
return -(widget.startOffset - startOffsetBase) * _containerExtent;
}
void updateRenderObject() {
void updateRenderObject(PageViewport oldWidget) {
renderObject.scrollDirection = widget.scrollDirection;
renderObject.overlayPainter = widget.overlayPainter;
super.updateRenderObject();
super.updateRenderObject(oldWidget);
}
double _containerExtent;

View File

@ -122,9 +122,9 @@ class _GridViewportElement extends VirtualViewportElement<GridViewport> {
double get startOffsetLimit =>_startOffsetLimit;
double _startOffsetLimit;
void updateRenderObject() {
void updateRenderObject(GridViewport oldWidget) {
renderObject.delegate = widget.delegate;
super.updateRenderObject();
super.updateRenderObject(oldWidget);
}
double _contentExtent;

View File

@ -135,12 +135,12 @@ class _ListViewportElement extends VirtualViewportElement<ListViewport> {
double get startOffsetLimit =>_startOffsetLimit;
double _startOffsetLimit;
void updateRenderObject() {
void updateRenderObject(ListViewport oldWidget) {
renderObject.scrollDirection = widget.scrollDirection;
renderObject.itemExtent = widget.itemExtent;
renderObject.padding = widget.padding;
renderObject.overlayPainter = widget.overlayPainter;
super.updateRenderObject();
super.updateRenderObject(oldWidget);
}
double _contentExtent;

View File

@ -43,7 +43,7 @@ abstract class VirtualViewportElement<T extends VirtualViewport> extends RenderO
_iterator = null;
_widgets = <Widget>[];
renderObject.callback = layout;
updateRenderObject();
updateRenderObject(null);
}
void unmount() {
@ -56,8 +56,9 @@ abstract class VirtualViewportElement<T extends VirtualViewport> extends RenderO
_iterator = null;
_widgets = <Widget>[];
}
T oldWidget = widget;
super.update(newWidget);
updateRenderObject();
updateRenderObject(oldWidget);
if (!renderObject.needsLayout)
_materializeChildren();
}
@ -73,7 +74,7 @@ abstract class VirtualViewportElement<T extends VirtualViewport> extends RenderO
}
}
void updateRenderObject() {
void updateRenderObject(T oldWidget) {
renderObject.virtualChildCount = widget.children.length;
if (startOffsetBase != null) {
@ -82,9 +83,22 @@ abstract class VirtualViewportElement<T extends VirtualViewport> extends RenderO
// If we don't already need layout, we need to request a layout if the
// viewport has shifted to expose new children.
if (!renderObject.needsLayout) {
if (startOffsetBase != null && widget.startOffset < startOffsetBase)
renderObject.markNeedsLayout();
else if (startOffsetLimit != null && widget.startOffset > startOffsetLimit)
bool shouldLayout = false;
if (startOffsetBase != null) {
if (widget.startOffset < startOffsetBase)
shouldLayout = true;
else if (widget.startOffset == startOffsetBase && oldWidget?.startOffset != startOffsetBase)
shouldLayout = true;
}
if (startOffsetLimit != null) {
if (widget.startOffset > startOffsetLimit)
shouldLayout = true;
else if (widget.startOffset == startOffsetLimit && oldWidget?.startOffset != startOffsetLimit)
shouldLayout = true;
}
if (shouldLayout)
renderObject.markNeedsLayout();
}
}