前提・実現したいこと
親クラスのメンバ変数で定義したリストデータをもとに、独自定義のクラス(StatefulWidget)をリスト表示したいです。
リンクにサンプルコードを記載しています。(下記に同じコード記載しています)
そもそも、この実装が不適切である場合や、推奨される実装があればご教授いただけますと幸いです。
List<CounterItem> _counterItems = List<CounterItem>.generate(30, (index) => CounterItem(0)); 〜〜〜〜〜〜〜〜〜〜 省略 〜〜〜〜〜〜〜〜〜〜 itemBuilder: (context, index) { // 1要素ずつ、レンダリングしていく return _counterItems[index]; },
上記 Listデータの各要素を、ListViewの項目にしたいと考えております。
発生している問題・エラーメッセージ
サンプルコードでは、CouterItem
のコンストラクタで初期化した値をstateクラスでinitState()
することで動的に値を変更しています。ですが、この実装だとコンストラクタで渡された値とは実体が異なるため、_MyHomePageState
のListView.builder
が実行される(スクロールする)ごとに値が消えてしまいます。
当初は、CounterItem
のメンバ変数(score)をfinal
修飾子を付けずに、widget.score
で値にアクセスするように実装していました。この実装の場合は、値をもとのリストが保持するため再描画されても値を保持できてました。しかし、statefulWidget
は@immutableアノテーションで定義するようにワーニングが表示されるので、別の実装庵を考えおります。
該当のソースコード
dart
1import 'package:flutter/material.dart'; 2 3void main() { 4 runApp(MyApp()); 5} 6 7class MyApp extends StatelessWidget { 8 9 Widget build(BuildContext context) { 10 return MaterialApp( 11 title: 'Flutter Demo', 12 home: MyHomePage(title: 'Flutter Demo Home Page'), 13 ); 14 } 15} 16 17class MyHomePage extends StatefulWidget { 18 MyHomePage({Key key, this.title}) : super(key: key); 19 final String title; 20 21 22 _MyHomePageState createState() => _MyHomePageState(); 23} 24 25class _MyHomePageState extends State<MyHomePage> { 26 // 状態も含め管理するデータを準備する 27 List<CounterItem> _counterItems = 28 List<CounterItem>.generate(30, (index) => CounterItem(0)); 29 30 31 Widget build(BuildContext context) { 32 return Scaffold( 33 appBar: AppBar( 34 title: Text(widget.title), 35 ), 36// 推測だが、builder関数は、スクロールされるたびに表示画面内の要素を再度レンダリングしているので、scoreが保持されない。 37 body: ListView.builder( 38 itemCount: _counterItems.length, 39 itemBuilder: (context, index) { 40 // 1要素ずつ、レンダリングしていく 41 return _counterItems[index]; 42 }, 43 ), 44 ); 45 } 46} 47 48// 以下のクラスを別ファイルに分割して、パーツとして管理したい 49class CounterItem extends StatefulWidget { 50 CounterItem(this.score); 51 final int score; 52 53 _CounterItemState createState() => _CounterItemState(); 54} 55 56class _CounterItemState extends State<CounterItem> { 57 int _score; 58 59 60 void initState() { 61 super.initState(); 62 _score = widget.score; // 値渡しすることになるので、大元のListデータに反映できない 63 } 64 65 66 Widget build(BuildContext context) { 67 return Container( 68 decoration: BoxDecoration( 69 border: Border(bottom: BorderSide(width: 1.0, color: Colors.grey))), 70 child: ListTile( 71 leading: ElevatedButton( 72 child: Text('カウント アップ'), 73 onPressed: () { 74 setState(() { 75 _score++; 76 // widget.score++; 77 }); 78 }, 79 ), 80 title: Text( 81 '$_score', 82 // '${widget.score}', 83 style: TextStyle(color: Colors.black, fontSize: 18.0), 84 ), 85 ), 86 ); 87 } 88}
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/12/26 08:42
2021/01/04 02:33