From 3c80df50403adca6fc3fbdc0af911de5e178a61a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E6=B4=B5=E9=94=8B?= Date: Fri, 17 Nov 2023 12:50:33 -0600 Subject: [PATCH] Fix NoSplash not being disposed (#138542) Fix https://github.com/flutter/flutter/issues/136441 --- .../flutter/lib/src/material/no_splash.dart | 13 ++++ .../test/material/ink_splash_test.dart | 64 +++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/packages/flutter/lib/src/material/no_splash.dart b/packages/flutter/lib/src/material/no_splash.dart index 561d1f0d3d2..38958a8c706 100644 --- a/packages/flutter/lib/src/material/no_splash.dart +++ b/packages/flutter/lib/src/material/no_splash.dart @@ -29,6 +29,7 @@ class _NoSplashFactory extends InteractiveInkFeatureFactory { controller: controller, referenceBox: referenceBox, color: color, + onRemoved: onRemoved, ); } } @@ -64,4 +65,16 @@ class NoSplash extends InteractiveInkFeature { @override void paintFeature(Canvas canvas, Matrix4 transform) { } + + @override + void confirm() { + super.confirm(); + dispose(); + } + + @override + void cancel() { + super.cancel(); + dispose(); + } } diff --git a/packages/flutter/test/material/ink_splash_test.dart b/packages/flutter/test/material/ink_splash_test.dart index ceb1c4b114f..77107939928 100644 --- a/packages/flutter/test/material/ink_splash_test.dart +++ b/packages/flutter/test/material/ink_splash_test.dart @@ -6,6 +6,39 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; +class Page extends StatefulWidget { + const Page({ + super.key, + required this.title, + required this.onDispose, + }); + + final String title; + + final void Function()? onDispose; + + @override + State createState() => _PageState(); +} + +class _PageState extends State { + @override + void dispose() { + widget.onDispose?.call(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Center( + child: FilledButton( + onPressed: () {}, + child: Text(widget.title), + ), + ); + } +} + void main() { // Regression test for https://github.com/flutter/flutter/issues/21506. testWidgetsWithLeakTracking('InkSplash receives textDirection', (WidgetTester tester) async { @@ -66,4 +99,35 @@ void main() { await tester.pumpAndSettle(); } }); + + // Regression test for https://github.com/flutter/flutter/issues/136441. + testWidgetsWithLeakTracking('PageView item can dispose when widget with NoSplash.splashFactory is tapped', (WidgetTester tester) async { + final PageController controller = PageController(); + final List disposedPageIndexes = []; + await tester.pumpWidget(MaterialApp( + theme: ThemeData(splashFactory: NoSplash.splashFactory), + home: Scaffold( + body: PageView.builder( + controller: controller, + itemBuilder: (BuildContext context, int index) { + return Page( + title: 'Page $index', + onDispose: () { + disposedPageIndexes.add(index); + }, + ); + }, + itemCount: 3, + ), + ), + )); + controller.jumpToPage(1); + await tester.pumpAndSettle(); + await tester.tap(find.text('Page 1')); + await tester.pumpAndSettle(); + controller.jumpToPage(0); + await tester.pumpAndSettle(); + expect(disposedPageIndexes, [0, 1]); + controller.dispose(); + }); }