Commit cc9d602b authored by Adam Barth's avatar Adam Barth

Block should work inside LazyBlock (#3546)

Previously we were locking down the state even when calling layout in
LazyBlock. Now we lock only when building children. Making this work well
involved moving the catch out of lockState and into the few callers who
actually wanted it.

Fixes #3534
parent 00f10da1
......@@ -285,7 +285,7 @@ class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWi
} else {
element.update(this);
}
}, building: true, context: 'while attaching root widget to rendering tree');
}, building: true);
return element;
}
......
......@@ -710,7 +710,7 @@ class BuildOwner {
///
/// The context argument is used to describe the scope in case an exception is
/// caught while invoking the callback.
void lockState(void callback(), { bool building: false, String context }) {
void lockState(void callback(), { bool building: false }) {
bool debugPreviouslyBuilding;
assert(_debugStateLockLevel >= 0);
assert(() {
......@@ -723,8 +723,6 @@ class BuildOwner {
});
try {
callback();
} catch (e, stack) {
_debugReportException(context, e, stack);
} finally {
assert(() {
_debugStateLockLevel -= 1;
......@@ -758,23 +756,25 @@ class BuildOwner {
if (_dirtyElements.isEmpty)
return;
Timeline.startSync('Build');
lockState(() {
_dirtyElements.sort(_elementSort);
int dirtyCount = _dirtyElements.length;
int index = 0;
while (index < dirtyCount) {
_dirtyElements[index].rebuild();
index += 1;
if (dirtyCount < _dirtyElements.length) {
_dirtyElements.sort(_elementSort);
dirtyCount = _dirtyElements.length;
try {
lockState(() {
_dirtyElements.sort(_elementSort);
int dirtyCount = _dirtyElements.length;
int index = 0;
while (index < dirtyCount) {
_dirtyElements[index].rebuild();
index += 1;
if (dirtyCount < _dirtyElements.length) {
_dirtyElements.sort(_elementSort);
dirtyCount = _dirtyElements.length;
}
}
}
assert(!_dirtyElements.any((BuildableElement element) => element.dirty));
assert(!_dirtyElements.any((BuildableElement element) => element.dirty));
}, building: true);
} finally {
_dirtyElements.clear();
}, building: true, context: 'while rebuilding dirty elements');
assert(_dirtyElements.isEmpty);
Timeline.finishSync();
Timeline.finishSync();
}
}
/// Complete the element build pass by unmounting any elements that are no
......@@ -789,12 +789,17 @@ class BuildOwner {
/// about changes to global keys will run.
void finalizeTree() {
Timeline.startSync('Finalize tree');
lockState(() {
_inactiveElements._unmountAll();
}, context: 'while finalizing the widget tree');
assert(GlobalKey._debugCheckForDuplicates);
scheduleMicrotask(GlobalKey._notifyListeners);
Timeline.finishSync();
try {
lockState(() {
_inactiveElements._unmountAll();
});
assert(GlobalKey._debugCheckForDuplicates);
scheduleMicrotask(GlobalKey._notifyListeners);
} catch (e, stack) {
_debugReportException('while finalizing the widget tree', e, stack);
} finally {
Timeline.finishSync();
}
}
/// Cause the entire subtree rooted at the given [Element] to
......
......@@ -164,7 +164,7 @@ abstract class VirtualViewportElement extends RenderObjectElement {
assert(startOffsetBase != null);
assert(startOffsetLimit != null);
_updatePaintOffset();
owner.lockState(_materializeChildren, building: true, context: 'during $runtimeType layout');
owner.lockState(_materializeChildren, building: true);
}
void _materializeChildren() {
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
import 'package:test/test.dart';
void main() {
test('Block inside LazyBlock', () {
testWidgets((WidgetTester tester) {
tester.pumpWidget(new LazyBlock(
delegate: new LazyBlockChildren(
children: <Widget>[
new Block(
children: <Widget>[
new Text('1'),
new Text('2'),
new Text('3'),
]
),
new Block(
children: <Widget>[
new Text('4'),
new Text('5'),
new Text('6'),
]
),
]
)
));
});
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment