| // Copyright 2017 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/widgets.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| |
| class Leaf extends StatefulWidget { |
| const Leaf({ Key key, this.child }) : super(key: key); |
| final Widget child; |
| @override |
| _LeafState createState() => new _LeafState(); |
| } |
| |
| class _LeafState extends State<Leaf> { |
| bool _keepAlive = false; |
| KeepAliveHandle _handle; |
| |
| @override |
| void deactivate() { |
| _handle?.release(); |
| _handle = null; |
| super.deactivate(); |
| } |
| |
| void setKeepAlive(bool value) { |
| _keepAlive = value; |
| if (_keepAlive) { |
| if (_handle == null) { |
| _handle = new KeepAliveHandle(); |
| new KeepAliveNotification(_handle).dispatch(context); |
| } |
| } else { |
| _handle?.release(); |
| _handle = null; |
| } |
| } |
| |
| @override |
| Widget build(BuildContext context) { |
| if (_keepAlive && _handle == null) { |
| _handle = new KeepAliveHandle(); |
| new KeepAliveNotification(_handle).dispatch(context); |
| } |
| return widget.child; |
| } |
| } |
| |
| List<Widget> generateList(Widget child, { @required bool impliedMode }) { |
| return new List<Widget>.generate( |
| 100, |
| (int index) { |
| final Widget result = new Leaf( |
| key: new GlobalObjectKey<_LeafState>(index), |
| child: child, |
| ); |
| if (impliedMode) |
| return result; |
| return new AutomaticKeepAlive(child: result); |
| }, |
| growable: false, |
| ); |
| } |
| |
| void tests({ @required bool impliedMode }) { |
| testWidgets('AutomaticKeepAlive with ListView with itemExtent', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| new Directionality( |
| textDirection: TextDirection.ltr, |
| child: new ListView( |
| addAutomaticKeepAlives: impliedMode, |
| addRepaintBoundaries: impliedMode, |
| itemExtent: 12.3, // about 50 widgets visible |
| cacheExtent: 0.0, |
| children: generateList(const Placeholder(), impliedMode: impliedMode), |
| ), |
| ), |
| ); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(30)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(59), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(60), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(61), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(90), skipOffstage: false), findsNothing); |
| await tester.drag(find.byType(ListView), const Offset(0.0, -300.0)); // about 25 widgets' worth |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(30)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(59)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(60)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(61)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(90), skipOffstage: false), findsNothing); |
| const GlobalObjectKey<_LeafState>(60).currentState.setKeepAlive(true); |
| await tester.drag(find.byType(ListView), const Offset(0.0, 300.0)); // back to top |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(30)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(59), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(60), skipOffstage: false), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(60)), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(61), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(90), skipOffstage: false), findsNothing); |
| const GlobalObjectKey<_LeafState>(60).currentState.setKeepAlive(false); |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(30)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(59), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(60), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(61), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(90), skipOffstage: false), findsNothing); |
| }); |
| |
| testWidgets('AutomaticKeepAlive with ListView without itemExtent', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| new Directionality( |
| textDirection: TextDirection.ltr, |
| child: new ListView( |
| addAutomaticKeepAlives: impliedMode, |
| addRepaintBoundaries: impliedMode, |
| cacheExtent: 0.0, |
| children: generateList( |
| new Container(height: 12.3, child: const Placeholder()), // about 50 widgets visible |
| impliedMode: impliedMode, |
| ), |
| ), |
| ), |
| ); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(30)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(59), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(60), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(61), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(90), skipOffstage: false), findsNothing); |
| await tester.drag(find.byType(ListView), const Offset(0.0, -300.0)); // about 25 widgets' worth |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(30)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(59)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(60)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(61)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(90), skipOffstage: false), findsNothing); |
| const GlobalObjectKey<_LeafState>(60).currentState.setKeepAlive(true); |
| await tester.drag(find.byType(ListView), const Offset(0.0, 300.0)); // back to top |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(30)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(59), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(60), skipOffstage: false), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(60)), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(61), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(90), skipOffstage: false), findsNothing); |
| const GlobalObjectKey<_LeafState>(60).currentState.setKeepAlive(false); |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(30)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(59), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(60), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(61), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(90), skipOffstage: false), findsNothing); |
| }); |
| |
| testWidgets('AutomaticKeepAlive with GridView', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| new Directionality( |
| textDirection: TextDirection.ltr, |
| child: new GridView.count( |
| addAutomaticKeepAlives: impliedMode, |
| addRepaintBoundaries: impliedMode, |
| crossAxisCount: 2, |
| childAspectRatio: 400.0 / 24.6, // about 50 widgets visible |
| cacheExtent: 0.0, |
| children: generateList( |
| new Container(child: const Placeholder()), |
| impliedMode: impliedMode, |
| ), |
| ), |
| ), |
| ); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(30)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(59), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(60), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(61), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(90), skipOffstage: false), findsNothing); |
| await tester.drag(find.byType(GridView), const Offset(0.0, -300.0)); // about 25 widgets' worth |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(30)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(59)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(60)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(61)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(90), skipOffstage: false), findsNothing); |
| const GlobalObjectKey<_LeafState>(60).currentState.setKeepAlive(true); |
| await tester.drag(find.byType(GridView), const Offset(0.0, 300.0)); // back to top |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(30)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(59), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(60), skipOffstage: false), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(60)), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(61), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(90), skipOffstage: false), findsNothing); |
| const GlobalObjectKey<_LeafState>(60).currentState.setKeepAlive(false); |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(30)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(59), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(60), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(61), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(90), skipOffstage: false), findsNothing); |
| }); |
| } |
| |
| void main() { |
| group('Explicit automatic keep-alive', () { tests(impliedMode: false); }); |
| group('Implied automatic keep-alive', () { tests(impliedMode: true); }); |
| |
| testWidgets('AutomaticKeepAlive double', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| new Directionality( |
| textDirection: TextDirection.ltr, |
| child: new ListView( |
| addAutomaticKeepAlives: false, |
| addRepaintBoundaries: false, |
| cacheExtent: 0.0, |
| children: <Widget>[ |
| new AutomaticKeepAlive( |
| child: new Container( |
| height: 400.0, |
| child: new Stack(children: const <Widget>[ |
| const Leaf(key: const GlobalObjectKey<_LeafState>(0), child: const Placeholder()), |
| const Leaf(key: const GlobalObjectKey<_LeafState>(1), child: const Placeholder()), |
| ]), |
| ), |
| ), |
| new AutomaticKeepAlive( |
| child: new Container( |
| key: const GlobalObjectKey<_LeafState>(2), |
| height: 400.0, |
| ), |
| ), |
| new AutomaticKeepAlive( |
| child: new Container( |
| key: const GlobalObjectKey<_LeafState>(3), |
| height: 400.0, |
| ), |
| ), |
| ], |
| ), |
| ), |
| ); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(1)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(2)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3), skipOffstage: false), findsNothing); |
| await tester.drag(find.byType(ListView), const Offset(0.0, -1000.0)); // move to bottom |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(1), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(2)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| await tester.drag(find.byType(ListView), const Offset(0.0, 1000.0)); // move to top |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(1)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(2)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3), skipOffstage: false), findsNothing); |
| const GlobalObjectKey<_LeafState>(0).currentState.setKeepAlive(true); |
| await tester.drag(find.byType(ListView), const Offset(0.0, -1000.0)); // move to bottom |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0), skipOffstage: false), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(1), skipOffstage: false), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0)), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(1)), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(2)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| const GlobalObjectKey<_LeafState>(1).currentState.setKeepAlive(true); |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0), skipOffstage: false), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(1), skipOffstage: false), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0)), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(1)), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(2)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| const GlobalObjectKey<_LeafState>(0).currentState.setKeepAlive(false); |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0), skipOffstage: false), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(1), skipOffstage: false), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0)), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(1)), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(2)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| const GlobalObjectKey<_LeafState>(1).currentState.setKeepAlive(false); |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(1), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(2)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| }); |
| |
| testWidgets('AutomaticKeepAlive double 2', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| new Directionality( |
| textDirection: TextDirection.ltr, |
| child: new ListView( |
| addAutomaticKeepAlives: false, |
| addRepaintBoundaries: false, |
| cacheExtent: 0.0, |
| children: <Widget>[ |
| new AutomaticKeepAlive( |
| child: new Container( |
| height: 400.0, |
| child: new Stack(children: const <Widget>[ |
| const Leaf(key: const GlobalObjectKey<_LeafState>(0), child: const Placeholder()), |
| const Leaf(key: const GlobalObjectKey<_LeafState>(1), child: const Placeholder()), |
| ]), |
| ), |
| ), |
| new AutomaticKeepAlive( |
| child: new Container( |
| height: 400.0, |
| child: new Stack(children: const <Widget>[ |
| const Leaf(key: const GlobalObjectKey<_LeafState>(2), child: const Placeholder()), |
| const Leaf(key: const GlobalObjectKey<_LeafState>(3), child: const Placeholder()), |
| ]), |
| ), |
| ), |
| new AutomaticKeepAlive( |
| child: new Container( |
| height: 400.0, |
| child: new Stack(children: const <Widget>[ |
| const Leaf(key: const GlobalObjectKey<_LeafState>(4), child: const Placeholder()), |
| const Leaf(key: const GlobalObjectKey<_LeafState>(5), child: const Placeholder()), |
| ]), |
| ), |
| ), |
| ], |
| ), |
| ), |
| ); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(1)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(2)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(4), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(5), skipOffstage: false), findsNothing); |
| const GlobalObjectKey<_LeafState>(0).currentState.setKeepAlive(true); |
| await tester.drag(find.byType(ListView), const Offset(0.0, -1000.0)); // move to bottom |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0), skipOffstage: false), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(1), skipOffstage: false), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(1)), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0)), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(2)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(4)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(5)), findsOneWidget); |
| await tester.pumpWidget(new Directionality( |
| textDirection: TextDirection.ltr, |
| child: new ListView( |
| addAutomaticKeepAlives: false, |
| addRepaintBoundaries: false, |
| cacheExtent: 0.0, |
| children: <Widget>[ |
| new AutomaticKeepAlive( |
| child: new Container( |
| height: 400.0, |
| child: new Stack(children: const <Widget>[ |
| const Leaf(key: const GlobalObjectKey<_LeafState>(1), child: const Placeholder()), |
| ]), |
| ), |
| ), |
| new AutomaticKeepAlive( |
| child: new Container( |
| height: 400.0, |
| child: new Stack(children: const <Widget>[ |
| const Leaf(key: const GlobalObjectKey<_LeafState>(2), child: const Placeholder()), |
| const Leaf(key: const GlobalObjectKey<_LeafState>(3), child: const Placeholder()), |
| ]), |
| ), |
| ), |
| new AutomaticKeepAlive( |
| child: new Container( |
| height: 400.0, |
| child: new Stack(children: const <Widget>[ |
| const Leaf(key: const GlobalObjectKey<_LeafState>(4), child: const Placeholder()), |
| const Leaf(key: const GlobalObjectKey<_LeafState>(5), child: const Placeholder()), |
| const Leaf(key: const GlobalObjectKey<_LeafState>(0), child: const Placeholder()), |
| ]), |
| ), |
| ), |
| ], |
| ), |
| )); |
| await tester.pump(); // Sometimes AutomaticKeepAlive needs an extra pump to clean things up. |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(1), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(2)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(4)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(5)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0)), findsOneWidget); |
| await tester.drag(find.byType(ListView), const Offset(0.0, 1000.0)); // move to top |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(1)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(2)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(4), skipOffstage: false), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(5), skipOffstage: false), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0), skipOffstage: false), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(4)), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(5)), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0)), findsNothing); |
| const GlobalObjectKey<_LeafState>(0).currentState.setKeepAlive(false); |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(1)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(2)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(4), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(5), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0), skipOffstage: false), findsNothing); |
| await tester.pumpWidget(new Directionality( |
| textDirection: TextDirection.ltr, |
| child: new ListView( |
| addAutomaticKeepAlives: false, |
| addRepaintBoundaries: false, |
| cacheExtent: 0.0, |
| children: <Widget>[ |
| new AutomaticKeepAlive( |
| child: new Container( |
| height: 400.0, |
| child: new Stack(children: const <Widget>[ |
| const Leaf(key: const GlobalObjectKey<_LeafState>(1), child: const Placeholder()), |
| const Leaf(key: const GlobalObjectKey<_LeafState>(2), child: const Placeholder()), |
| ]), |
| ), |
| ), |
| new AutomaticKeepAlive( |
| child: new Container( |
| height: 400.0, |
| child: new Stack(children: const <Widget>[ |
| ]), |
| ), |
| ), |
| new AutomaticKeepAlive( |
| child: new Container( |
| height: 400.0, |
| child: new Stack(children: const <Widget>[ |
| const Leaf(key: const GlobalObjectKey<_LeafState>(3), child: const Placeholder()), |
| const Leaf(key: const GlobalObjectKey<_LeafState>(4), child: const Placeholder()), |
| const Leaf(key: const GlobalObjectKey<_LeafState>(5), child: const Placeholder()), |
| const Leaf(key: const GlobalObjectKey<_LeafState>(0), child: const Placeholder()), |
| ]), |
| ), |
| ), |
| ], |
| ), |
| )); |
| await tester.pump(); // Sometimes AutomaticKeepAlive needs an extra pump to clean things up. |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(1)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(2)), findsOneWidget); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(3), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(4), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(5), skipOffstage: false), findsNothing); |
| expect(find.byKey(const GlobalObjectKey<_LeafState>(0), skipOffstage: false), findsNothing); |
| }); |
| |
| testWidgets('AutomaticKeepAlive with keepAlive set to true before initState', (WidgetTester tester) async { |
| await tester.pumpWidget(new Directionality( |
| textDirection: TextDirection.ltr, |
| child: new ListView.builder( |
| itemCount: 50, |
| itemBuilder: (BuildContext context, int index){ |
| if (index == 0){ |
| return const _AlwaysKeepAlive( |
| key: const GlobalObjectKey<_AlwaysKeepAliveState>(0), |
| ); |
| } |
| return new Container( |
| height: 44.0, |
| child: new Text('FooBar $index'), |
| ); |
| }, |
| ), |
| )); |
| |
| expect(find.text('keep me alive'), findsOneWidget); |
| expect(find.text('FooBar 1'), findsOneWidget); |
| expect(find.text('FooBar 2'), findsOneWidget); |
| |
| expect(find.byKey(const GlobalObjectKey<_AlwaysKeepAliveState>(0)), findsOneWidget); |
| await tester.drag(find.byType(ListView), const Offset(0.0, -1000.0)); // move to bottom |
| await tester.pump(); |
| expect(find.byKey(const GlobalObjectKey<_AlwaysKeepAliveState>(0), skipOffstage: false), findsOneWidget); |
| |
| expect(find.text('keep me alive', skipOffstage: false), findsOneWidget); |
| expect(find.text('FooBar 1'), findsNothing); |
| expect(find.text('FooBar 2'), findsNothing); |
| }); |
| } |
| |
| class _AlwaysKeepAlive extends StatefulWidget { |
| const _AlwaysKeepAlive({Key key}) : super(key: key); |
| |
| @override |
| State<StatefulWidget> createState() => new _AlwaysKeepAliveState(); |
| } |
| |
| class _AlwaysKeepAliveState extends State<_AlwaysKeepAlive> with AutomaticKeepAliveClientMixin<_AlwaysKeepAlive> { |
| @override |
| bool get wantKeepAlive => true; |
| |
| @override |
| Widget build(BuildContext context) { |
| super.build(context); |
| return new Container( |
| height: 48.0, |
| child: const Text('keep me alive'), |
| ); |
| } |
| } |