Skip to content

Instantly share code, notes, and snippets.

@kezhuw
Created November 13, 2017 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kezhuw/3ff4cf46d2d60565960caf2257cd1242 to your computer and use it in GitHub Desktop.
Save kezhuw/3ff4cf46d2d60565960caf2257cd1242 to your computer and use it in GitHub Desktop.
Widget got rebuilt due to outdated dependencies
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
class ConditionInherited extends InheritedWidget {
const ConditionInherited({this.value, Key key, Widget child}) : super(key: key, child: child);
final bool value;
static bool valueOf(BuildContext context) {
final ConditionInherited widget = context.inheritFromWidgetOfExactType(ConditionInherited);
return widget?.value ?? true;
}
@override
bool updateShouldNotify(ConditionInherited oldWidget) => value != oldWidget.value;
}
class StringInherited extends InheritedWidget {
const StringInherited({this. value, Key key, Widget child}) : super(key: key, child: child);
final String value;
static String valueOf(BuildContext context) {
final StringInherited widget = context.inheritFromWidgetOfExactType(StringInherited);
return widget?.value ?? 'Missing string value';
}
@override
bool updateShouldNotify(StringInherited oldWidget) => value != oldWidget.value;
}
class ConditionalText extends StatefulWidget {
const ConditionalText({this.textKey, this.logger, Key key}) : super(key: key);
final Key textKey;
final Logger logger;
@override
ConditionalTextElement createElement() => new ConditionalTextElement(this);
@override
ConditionalTextState createState() => new ConditionalTextState();
}
class ConditionalTextElement extends StatefulElement {
ConditionalTextElement(ConditionalText widget) : super(widget);
@override
ConditionalText get widget => super.widget;
@override
void didChangeDependencies() {
super.didChangeDependencies();
widget.logger('Element.didChangeDependencies');
}
}
class ConditionalTextState extends State<ConditionalText> {
@override
Widget build(BuildContext context) {
widget.logger('build');
final bool condition = ConditionInherited.valueOf(context);
if (condition) {
final String string = StringInherited.valueOf(context);
return new Text(string, key: widget.textKey, textDirection: TextDirection.ltr);
}
return new Text('No Text', key: widget.textKey, textDirection: TextDirection.ltr);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
widget.logger('State.didChangeDependencies');
}
}
typedef void Logger(String s);
Logger newLogger(List<String> log, {String prefix = '', List<String> excludes = const <String>[]}) {
if (prefix != '')
prefix = prefix + ' ';
return (String s) {
if (excludes.contains(s)) {
return;
}
log.add(prefix + s);
};
}
Widget buildHierarchicalInheritedWidgetTree({bool condition, String text, Widget child}) {
return new StringInherited(
value: text,
child: new ConditionInherited(
value: condition,
child: child,
)
);
}
void main() {
testWidgets('didChangeDependencies is not called due to outdated dependency change', (WidgetTester tester) async {
final List<String> log = <String>[];
final Widget widget = new ConditionalText(logger: newLogger(log));
await tester.pumpWidget(buildHierarchicalInheritedWidgetTree(
condition: true,
text: 'Foo',
child: widget,
));
await tester.pumpWidget(buildHierarchicalInheritedWidgetTree(
condition: false,
text: 'Bar',
child: widget,
));
// From now on, we don't depend on StringInherited widget.
// But we do rebuild due to change of it.
log.clear();
await tester.pumpWidget(buildHierarchicalInheritedWidgetTree(
condition: false,
text: 'FooBar',
child: widget,
));
expect(log, <String>[]);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment