Index
タイトルの通り、Navigationbarで画面切り返した時に、変数が初期化されてしまうので、困っていました。
こんな感じの現象です↓
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
import 'package:flutter/material.dart'; import 'package:indexstack/counter.dart'; import 'package:indexstack/dammy.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { var _selectedIndex = 0; final List<Widget> _widgetList = <Widget>[ const Counter(), const Dammy(), ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), bottomNavigationBar: NavigationBar( destinations: const [ NavigationDestination(icon: Icon(Icons.abc), label: 'count'), NavigationDestination(icon: Icon(Icons.ac_unit), label: 'dammy'), ], onDestinationSelected: (index) => setState( () { _selectedIndex = index; }, ), selectedIndex: _selectedIndex, ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[_widgetList.elementAt(_selectedIndex)], ), ), ); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
import 'package:flutter/material.dart'; class Counter extends StatefulWidget { const Counter({Key? key}) : super(key: key); @override State<Counter> createState() => _CounterState(); } class _CounterState extends State<Counter> { int _counter = 0; @override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ ElevatedButton( onPressed: _incrementCounter, child: const Text('count'), ), Text( '$_counter', style: Theme.of(context).textTheme.headline4, ), ], ), ); } @override void initState() { super.initState(); print('intiState'); } @override void didChangeDependencies() { super.didChangeDependencies(); print('didChangeDependencies'); } @override void dispose() { super.dispose(); print('dispose'); } @override void didUpdateWidget(covariant Counter oldWidget) { super.didUpdateWidget(oldWidget); print('didUpdateWidget'); } void _incrementCounter() { setState(() { _counter++; }); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import 'package:flutter/material.dart'; class Dammy extends StatefulWidget { const Dammy({Key? key}) : super(key: key); @override State<Dammy> createState() => _DammyState(); } class _DammyState extends State<Dammy> { @override Widget build(BuildContext context) { return const Text('Home'); } } |
なぜ変数が初期化されてしまうのか?
それはLifecycleを確認するとわかりました。
下記のlogから画面切り替えを行うと画面が破棄されていることがわかります。
画面が破棄されているので、変数の値も破棄されているわけです。
1 2 3 4 5 6 7 8 |
//アプリ起動 flutter: intiState flutter: didChangeDependencies //Dammy画面に切り替え flutter: dispose //Counter画面に切り替え flutter: intiState flutter: didChangeDependencies |
IndexedStackを使いましょう。
具体的にはmain.dartの以下の部分を
1 2 3 4 5 6 |
body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[_widgetList.elementAt(_selectedIndex)], ), ), |
このように書き換えます。
1 2 3 4 5 6 |
body: Center( child: IndexedStack( index: _selectedIndex, children: _widgetList, ), ), |
変更後の動作はこんな感じ。
logはこんな感じ。
disposeされなくなったことがわかります。
1 2 |
flutter: intiState flutter: didChangeDependencies |
修正後のコードはgitにあげております。