Fix/ValueListenableBuilder rebuilds (#72707)

This commit is contained in:
Bogdan Lukin 2021-02-04 06:06:05 +07:00 committed by GitHub
parent 7711c1ef8f
commit 69882d9647
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 1 deletions

View file

@ -179,7 +179,9 @@ class _ValueListenableBuilderState<T> extends State<ValueListenableBuilder<T>> {
}
void _valueChanged() {
setState(() { value = widget.valueListenable.value; });
if (value != widget.valueListenable.value) {
setState(() { value = widget.valueListenable.value; });
}
}
@override

View file

@ -9,6 +9,7 @@ import 'package:flutter/widgets.dart';
void main() {
late SpyStringValueNotifier valueListenable;
late Widget textBuilderUnderTest;
late int rebuildCount;
Widget builderForValueListenable(
ValueListenable<String?> valueListenable,
@ -18,6 +19,8 @@ void main() {
child: ValueListenableBuilder<String?>(
valueListenable: valueListenable,
builder: (BuildContext context, String? value, Widget? child) {
rebuildCount += 1;
if (value == null)
return const Placeholder();
return Text(value);
@ -29,6 +32,7 @@ void main() {
setUp(() {
valueListenable = SpyStringValueNotifier(null);
textBuilderUnderTest = builderForValueListenable(valueListenable);
rebuildCount = 0;
});
testWidgets('Null value is ok', (WidgetTester tester) async {
@ -58,6 +62,46 @@ void main() {
expect(find.text('Dinesh'), findsOneWidget);
});
testWidgets('Widget does not rebuilds if value is the same', (WidgetTester tester) async {
const Duration duration = Duration(milliseconds: 100);
final AnimationController controller = AnimationController(
vsync: const TestVSync(),
duration: duration,
)..value = 0;
final Animation<String> animation = TweenSequence<String>(<TweenSequenceItem<String>>[
TweenSequenceItem<String>(tween: ConstantTween<String>('Gilfoyle'), weight: 1.0),
TweenSequenceItem<String>(tween: ConstantTween<String>('Dinesh'), weight: 1.0),
]).animate(controller);
final Finder finder1 = find.text('Gilfoyle');
final Finder finder2 = find.text('Dinesh');
await tester.pumpWidget(builderForValueListenable(animation));
await tester.pump();
expect(finder1, findsOneWidget);
expect(finder2, findsNothing);
expect(rebuildCount, equals(1));
controller.value = 0.3;
await tester.pump();
expect(finder1, findsOneWidget);
expect(finder2, findsNothing);
expect(rebuildCount, equals(1));
controller.animateTo(0.6);
await tester.pumpAndSettle(duration);
expect(finder1, findsNothing);
expect(finder2, findsOneWidget);
expect(rebuildCount, equals(2));
controller.forward();
await tester.pumpAndSettle(duration);
expect(finder1, findsNothing);
expect(finder2, findsOneWidget);
expect(rebuildCount, equals(2));
});
testWidgets('Can change listenable', (WidgetTester tester) async {
await tester.pumpWidget(textBuilderUnderTest);