Commit 1ff7109b authored by Adam Barth's avatar Adam Barth

Mark State.setState as protected (#4295)

This required refactoring some cases where we weren't following the rules for
the protected annotation.
parent 88d47d57
......@@ -35,6 +35,12 @@ class ComplexLayoutAppState extends State<ComplexLayoutApp> {
_lightTheme = value;
});
}
void toggleAnimationSpeed() {
setState(() {
timeDilation = (timeDilation != 1.0) ? 1.0 : 5.0;
});
}
}
class ComplexLayout extends StatefulWidget {
......@@ -566,12 +572,6 @@ class GalleryDrawer extends StatelessWidget {
ComplexLayoutApp.of(context).lightTheme = value;
}
void _toggleAnimationSpeed(BuildContext context) {
ComplexLayoutApp.of(context).setState(() {
timeDilation = (timeDilation != 1.0) ? 1.0 : 5.0;
});
}
@override
Widget build(BuildContext context) {
return new Drawer(
......@@ -612,13 +612,13 @@ class GalleryDrawer extends StatelessWidget {
new DrawerItem(
icon: Icons.hourglass_empty,
selected: timeDilation != 1.0,
onPressed: () { _toggleAnimationSpeed(context); },
onPressed: () { ComplexLayoutApp.of(context).toggleAnimationSpeed(); },
child: new Row(
children: <Widget>[
new Flexible(child: new Text('Animate Slowly')),
new Checkbox(
value: timeDilation != 1.0,
onChanged: (bool value) { _toggleAnimationSpeed(context); }
onChanged: (bool value) { ComplexLayoutApp.of(context).toggleAnimationSpeed(); }
)
]
)
......
......@@ -8,8 +8,6 @@ import 'package:stocks/stock_data.dart' as stock_data;
const Duration kBenchmarkTime = const Duration(seconds: 15);
void _doNothing() { }
Future<Null> main() async {
assert(false); // don't run this in checked mode! Use --release.
stock_data.StockDataFetcher.actuallyFetchData = false;
......@@ -26,12 +24,12 @@ Future<Null> main() async {
await tester.pump(const Duration(seconds: 1)); // Complete drawer animation
final stocks.StocksAppState appState = tester.state(find.byType(stocks.StocksApp));
final BuildableElement appState = tester.element(find.byType(stocks.StocksApp));
final BuildOwner buildOwner = WidgetsBinding.instance.buildOwner;
watch.start();
while (watch.elapsed < kBenchmarkTime) {
appState.setState(_doNothing);
appState.markNeedsBuild();
buildOwner.buildDirtyElements();
iterations += 1;
}
......
......@@ -405,6 +405,7 @@ abstract class State<T extends StatefulWidget> {
/// If you just change the state directly without calling setState(), then the
/// widget will not be scheduled for rebuilding, meaning that its rendering
/// will not be updated.
@protected
void setState(VoidCallback fn) {
assert(() {
if (_debugLifecycleState == _StateLifecycle.defunct) {
......
......@@ -196,15 +196,13 @@ class LazyBlock extends StatelessWidget {
double contentExtent,
double containerExtent,
double minScrollOffset) {
state.setState(() {
final BoundedBehavior scrollBehavior = state.scrollBehavior;
state.didUpdateScrollBehavior(scrollBehavior.updateExtents(
contentExtent: contentExtent,
containerExtent: containerExtent,
minScrollOffset: minScrollOffset,
scrollOffset: state.scrollOffset
));
});
final BoundedBehavior scrollBehavior = state.scrollBehavior;
state.didUpdateScrollBehavior(scrollBehavior.updateExtents(
contentExtent: contentExtent,
containerExtent: containerExtent,
minScrollOffset: minScrollOffset,
scrollOffset: state.scrollOffset
));
}
Widget _buildViewport(BuildContext context, ScrollableState state, double scrollOffset) {
......
......@@ -63,14 +63,13 @@ class OverlayEntry {
set opaque (bool value) {
if (_opaque == value)
return;
_opaque = value;
assert(_overlay != null);
_overlay.setState(() {
_opaque = value;
});
_overlay._didChangeEntryOpacity();
}
OverlayState _overlay;
final GlobalKey _key = new GlobalKey();
final GlobalKey<_OverlayEntryState> _key = new GlobalKey<_OverlayEntryState>();
/// Remove this entry from the overlay.
void remove() {
......@@ -82,7 +81,7 @@ class OverlayEntry {
///
/// You need to call this function if the output of [builder] has changed.
void markNeedsBuild() {
_key.currentState?.setState(() { /* the state that changed is in the builder */ });
_key.currentState?._markNeedsBuild();
}
@override
......@@ -101,6 +100,10 @@ class _OverlayEntry extends StatefulWidget {
class _OverlayEntryState extends State<_OverlayEntry> {
@override
Widget build(BuildContext context) => config.entry.builder(context);
void _markNeedsBuild() {
setState(() { /* the state that changed is in the builder */ });
}
}
/// A [Stack] of entries that can be managed independently.
......@@ -245,6 +248,13 @@ class OverlayState extends State<Overlay> {
return result;
}
void _didChangeEntryOpacity() {
setState(() {
// We use the opacity of the entry in our build function, which means we
// our state has changed.
});
}
@override
Widget build(BuildContext context) {
List<Widget> backwardsChildren = <Widget>[];
......
......@@ -394,6 +394,13 @@ class _ModalScopeState extends State<_ModalScope> {
});
}
void _didChangeRouteOffStage() {
setState(() {
// We use the route's offstage bool in our build function, which means our
// state has changed.
});
}
@override
Widget build(BuildContext context) {
Widget contents = new PageStorage(
......@@ -515,14 +522,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
if (_offstage == value)
return;
_offstage = value;
_scopeKey.currentState?.setState(() {
// _offstage is the value we're setting, but since there might not be a
// state, we set it outside of this callback (which will only be called if
// there's a state currently built).
// _scopeKey is the key for the _ModalScope built in _buildModalScope().
// When we mark that state dirty, it'll rebuild itself, and use our
// offstage (via their config.route.offstage) when building.
});
_scopeKey.currentState?._didChangeRouteOffStage();
}
/// The build context for the subtree containing the primary content of this route.
......
......@@ -402,6 +402,7 @@ class ScrollableState<T extends Scrollable> extends State<T> {
/// If there are no in-progress scrolling physics, this function scrolls to
/// the given offset instead.
void didUpdateScrollBehavior(double newScrollOffset) {
setState(() { /* The scroll behavior is part of our build state. */ });
assert(_controller.isAnimating || _simulation == null);
if (_numberOfInProgressScrolls > 0) {
if (_simulation != null) {
......
......@@ -67,13 +67,11 @@ class ScrollableGrid extends StatelessWidget {
final Iterable<Widget> children;
void _handleExtentsChanged(ScrollableState state, double contentExtent, double containerExtent) {
state.setState(() {
state.didUpdateScrollBehavior(state.scrollBehavior.updateExtents(
contentExtent: contentExtent,
containerExtent: containerExtent,
scrollOffset: state.scrollOffset
));
});
state.didUpdateScrollBehavior(state.scrollBehavior.updateExtents(
contentExtent: contentExtent,
containerExtent: containerExtent,
scrollOffset: state.scrollOffset
));
}
Widget _buildViewport(BuildContext context, ScrollableState state, double scrollOffset) {
......
......@@ -102,13 +102,11 @@ class ScrollableList extends StatelessWidget {
final Iterable<Widget> children;
void _handleExtentsChanged(ScrollableState state, double contentExtent, double containerExtent) {
state.setState(() {
state.didUpdateScrollBehavior(state.scrollBehavior.updateExtents(
contentExtent: itemsWrap ? double.INFINITY : contentExtent,
containerExtent: containerExtent,
scrollOffset: state.scrollOffset
));
});
state.didUpdateScrollBehavior(state.scrollBehavior.updateExtents(
contentExtent: itemsWrap ? double.INFINITY : contentExtent,
containerExtent: containerExtent,
scrollOffset: state.scrollOffset
));
}
Widget _buildViewport(BuildContext context, ScrollableState state, double scrollOffset) {
......@@ -428,13 +426,11 @@ class ScrollableLazyList extends StatelessWidget {
final EdgeInsets padding;
void _handleExtentsChanged(ScrollableState state, double contentExtent, double containerExtent) {
state.setState(() {
state.didUpdateScrollBehavior(state.scrollBehavior.updateExtents(
contentExtent: contentExtent,
containerExtent: containerExtent,
scrollOffset: state.scrollOffset
));
});
state.didUpdateScrollBehavior(state.scrollBehavior.updateExtents(
contentExtent: contentExtent,
containerExtent: containerExtent,
scrollOffset: state.scrollOffset
));
}
Widget _buildViewport(BuildContext context, ScrollableState state, double scrollOffset) {
......
......@@ -37,11 +37,11 @@ class ProbeWidgetState extends State<ProbeWidget> {
class BadWidget extends StatelessWidget {
BadWidget(this.parentState);
final State parentState;
final BadWidgetParentState parentState;
@override
Widget build(BuildContext context) {
parentState.setState(() {});
parentState._markNeedsBuild();
return new Container();
}
}
......@@ -52,6 +52,13 @@ class BadWidgetParent extends StatefulWidget {
}
class BadWidgetParentState extends State<BadWidgetParent> {
void _markNeedsBuild() {
setState(() {
// Our state didn't really change, but we're doing something pathological
// here to trigger an interesting scenario to test.
});
}
@override
Widget build(BuildContext context) {
return new BadWidget(this);
......
......@@ -75,7 +75,7 @@ void main() {
StatefulElement outerElement = tester.element(find.byKey(outerKey));
expect(outerElement.state.config, equals(outer2));
outerElement.state.setState(() {});
outerElement.markNeedsBuild();
await tester.pump();
expect(tester.element(find.byKey(innerKey)), equals(innerElement));
......
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