Commit b803d187 authored by Ian Hickson's avatar Ian Hickson

Catch async functions passed to setState(). (#3992)

parent fc610604
......@@ -416,7 +416,22 @@ abstract class State<T extends StatefulWidget> {
}
return true;
});
fn();
dynamic result = fn() as dynamic;
assert(() {
if (result is Future) {
throw new FlutterError(
'setState() callback argument returned a Future.\n'
'The setState() method on $this was invoked with a closure or method that '
'returned a Future. Maybe it is marked as "async".\n'
'Instead of performing asynchronous work inside a call to setState(), first '
'execute the work (without updating the widget state), and then synchronously '
'update the state inside a call to setState().'
);
}
// We ignore other types of return values so that you can do things like:
// setState(() => x = 3);
return true;
});
_element.markNeedsBuild();
}
......
// Copyright 2015 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/widgets.dart';
class Changer extends StatefulWidget {
@override
ChangerState createState() => new ChangerState();
}
class ChangerState extends State<Changer> {
void test0() { setState(() { }); }
void test1() { setState(() => 1); }
void test2() { setState(() async { }); }
@override
Widget build(BuildContext context) => new Text('test');
}
void main() {
testWidgets('setState() catches being used with an async callback', (WidgetTester tester) async {
await tester.pumpWidget(new Changer());
ChangerState s = tester.state(find.byType(Changer));
expect(s.test0, isNot(throws));
expect(s.test1, isNot(throws));
expect(s.test2, throws);
});
}
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