注: 通常のアプリの実行ではすべて正常に動作します。問題は統合テストの実行中にのみ発生します。
Flutter Channel 安定版 2.2.3 を使用しており、統合テストには flutter SDK の「integration_test: sdk: flutter」を使用しています。</p>
Screen#1 から Screen#2 に移動した後Navigator.of(context).pushNamed(ScreenTwo, arguments: counterProvider);
、dispose() メソッドを介して Screen#1 が呼び出されます。状態管理に Provider を使用しています。プロバイダは Screen#1 で作成され、Screen#2 に渡されます。以下のエラーが表示されます。
エラー: CounterProvider が破棄された後に使用されました。CounterProvider で dispose() を呼び出すと、それは使用できなくなります。
これは、Screen#2 ページに移動した後に Screen#1 ページが破棄されているために発生しています。
この問題に直面した人はいますか? または、移動後に破棄されたメソッドが呼び出されるのを防ぐ方法を知っている人はいますか? </p>
統合テスト中にのみ発生します。
プロジェクトへのリンク: https://bitbucket.org/UrimGashiABC/test-dispose-issuesample/src/master/
スクリーン#1 クラス:
class ScreenOnePage extends StatefulWidget {
@override
_ScreenOnePageState createState() => _ScreenOnePageState();
}
class _ScreenOnePageState extends State<ScreenOnePage> {
@override
Widget build(BuildContext context) {
CounterProvider counterProvider = Provider.of<CounterProvider>(
context,
listen: true,
);
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Screen #1',
),
SizedBox(
height: 150,
),
Text(
'${counterProvider.counter}',
style: Theme.of(context).textTheme.headline4,
),
SizedBox(
height: 150,
),
TextButton(
key: const Key('screen_one_text_button'),
onPressed: () {
Navigator.of(context).pushNamed(ScreenTwo, arguments: counterProvider);
},
child: Text('Go to screen#2'),
),
],
),
),
floatingActionButton: FloatingActionButton(
key: const Key('screen_one_floating_button'),
onPressed: () => counterProvider.increaseCounter(),
tooltip: 'Increment',
child: Icon(Icons.add),
), //
);
}
}
スクリーン#2 クラス:
class ScreenTwoPage extends StatefulWidget {
@override
_ScreenTwoPageState createState() => _ScreenTwoPageState();
}
class _ScreenTwoPageState extends State<ScreenTwoPage> {
@override
Widget build(BuildContext context) {
CounterProvider counterProvider = Provider.of<CounterProvider>(
context,
listen: false,
);
return Scaffold(
appBar: AppBar(),
body: Container(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'Screen #2',
key: const Key('screen_two_title'),
),
SizedBox(
height: 150,
),
Text(
'Counter: ${counterProvider.counter}',
key: const Key('screen_two_counter'),
),
],
),
),
),
);
}
}
プロバイダー クラス:
class CounterProvider extends ChangeNotifier{
int counter = 0;
void increaseCounter(){
counter++;
notifyListeners();
}
}
テストクラス:
void main(){
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
testWidgets('counter test', (WidgetTester tester) async {
app.main();
await tester.pumpAndSettle();
final Finder screenOneButton = find.byKey(const Key('screen_one_text_button'));
final Finder screenOneFloatingButton = find.byKey(const Key('screen_one_floating_button'));
final Finder screenTwoTitle = find.byKey(const Key('screen_two_title'));
final Finder screenTwoCounter = find.byKey(const Key('screen_two_counter'));
await tester.tap(screenOneFloatingButton);
await tester.tap(screenOneButton);
await tester.pumpAndSettle();
expect(screenTwoTitle, findsOneWidget);
});
}