Skip to content

Commit fb110b9

Browse files
Fix memory leaks in MaterialBanner (flutter#146963)
1 parent c83d650 commit fb110b9

File tree

2 files changed

+31
-8
lines changed

2 files changed

+31
-8
lines changed

packages/flutter/lib/src/material/banner.dart

+26-7
Original file line numberDiff line numberDiff line change
@@ -267,11 +267,15 @@ class MaterialBanner extends StatefulWidget {
267267

268268
class _MaterialBannerState extends State<MaterialBanner> {
269269
bool _wasVisible = false;
270+
CurvedAnimation? _heightAnimation;
271+
CurvedAnimation? _slideOutCurvedAnimation;
270272

271273
@override
272274
void initState() {
273275
super.initState();
274276
widget.animation?.addStatusListener(_onAnimationStatusChanged);
277+
_setCurvedAnimations();
278+
275279
}
276280

277281
@override
@@ -280,12 +284,31 @@ class _MaterialBannerState extends State<MaterialBanner> {
280284
if (widget.animation != oldWidget.animation) {
281285
oldWidget.animation?.removeStatusListener(_onAnimationStatusChanged);
282286
widget.animation?.addStatusListener(_onAnimationStatusChanged);
287+
_setCurvedAnimations();
283288
}
284289
}
285290

291+
void _setCurvedAnimations() {
292+
_heightAnimation?.dispose();
293+
_slideOutCurvedAnimation?.dispose();
294+
if (widget.animation != null) {
295+
_heightAnimation = CurvedAnimation(parent: widget.animation!, curve: _materialBannerHeightCurve);
296+
_slideOutCurvedAnimation = CurvedAnimation(
297+
parent: widget.animation!,
298+
curve: const Threshold(0.0),
299+
);
300+
} else {
301+
_heightAnimation = null;
302+
_slideOutCurvedAnimation = null;
303+
}
304+
305+
}
306+
286307
@override
287308
void dispose() {
288309
widget.animation?.removeStatusListener(_onAnimationStatusChanged);
310+
_heightAnimation?.dispose();
311+
_slideOutCurvedAnimation?.dispose();
289312
super.dispose();
290313
}
291314

@@ -408,14 +431,10 @@ class _MaterialBannerState extends State<MaterialBanner> {
408431
child: materialBanner,
409432
);
410433

411-
final CurvedAnimation heightAnimation = CurvedAnimation(parent: widget.animation!, curve: _materialBannerHeightCurve);
412434
final Animation<Offset> slideOutAnimation = Tween<Offset>(
413435
begin: const Offset(0.0, -1.0),
414436
end: Offset.zero,
415-
).animate(CurvedAnimation(
416-
parent: widget.animation!,
417-
curve: const Threshold(0.0),
418-
));
437+
).animate(_slideOutCurvedAnimation!);
419438

420439
materialBanner = Semantics(
421440
container: true,
@@ -436,11 +455,11 @@ class _MaterialBannerState extends State<MaterialBanner> {
436455
materialBannerTransition = materialBanner;
437456
} else {
438457
materialBannerTransition = AnimatedBuilder(
439-
animation: heightAnimation,
458+
animation: _heightAnimation!,
440459
builder: (BuildContext context, Widget? child) {
441460
return Align(
442461
alignment: AlignmentDirectional.bottomStart,
443-
heightFactor: heightAnimation.value,
462+
heightFactor: _heightAnimation!.value,
444463
child: child,
445464
);
446465
},

packages/flutter/test/material/banner_theme_test.dart

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'package:flutter/material.dart';
66
import 'package:flutter/rendering.dart';
77
import 'package:flutter_test/flutter_test.dart';
8+
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
89

910
void main() {
1011
test('MaterialBannerThemeData copyWith, ==, hashCode basics', () {
@@ -324,7 +325,10 @@ void main() {
324325
expect(find.byType(Divider), findsNothing);
325326
});
326327

327-
testWidgets('MaterialBanner widget properties take priority over theme when presented by ScaffoldMessenger', (WidgetTester tester) async {
328+
testWidgets('MaterialBanner widget properties take priority over theme when presented by ScaffoldMessenger',
329+
// TODO(polina-c): remove when fixed https://github.com/flutter/flutter/issues/145600 [leak-tracking-opt-in]
330+
experimentalLeakTesting: LeakTesting.settings.withTracked(classes: const <String>['CurvedAnimation']),
331+
(WidgetTester tester) async {
328332
const Color backgroundColor = Colors.purple;
329333
const double elevation = 6.0;
330334
const TextStyle textStyle = TextStyle(color: Colors.green);

0 commit comments

Comments
 (0)