前回(上記事)では、reorderableListviewを使ったのですが、その時は、
状態管理には、ステートフル・setState()を使用していました。故に、ReorderableListViewを使う場所は、静的(Scaffoldのbodyにそのまま)に呼び出していて、flutter.devのサンプル通り、うまく動きました。
今回は、状態管理に、providerを使いました。そうすると、どうなるかというと、前回使用していたsetState()ではなく、(今回は)別ファイル(provider.dart)にメソッドを定義し、そのメソッドが状態に反映される様に、main.dartで、その準備設定をしておく、その後で、前回表示した様に、ReorderableListViewを(Scaffoldのbodyに)呼び出す、という流れになるわけです。
(bodyにそのまま呼び出すと、provider登録したメソッドを呼び出す場所で、エラー(Instance member ‘recorderItems’ can’t be accessed using static access.(インスタンスメンバーなので、クラス名を使って静的にアクセスすることはできません。))が発生します。)
こうならない為に、ちょっとだけコツがあって、(動的に呼び出さないといけない、という仕様があるので)、結論から言うと、Scaffoldのbodyに呼び出すときは、Consumerのbuilderを使います。
(こうすることで、(Provider パッケージを使用して状態管理を行っているので)事前準備したproviderのインスタンスを、providerから取得して、メソッドを正常に呼び出せる様になります。)
1.エラー発生場所
以下の状態管理設定済みのメソッド(recorderItems、removeItems)を呼び出すところで、エラーが発生しました。
class TaskList2 extends StatelessWidget {
const TaskList2({super.key});
// リストアイテムを生成します
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('ReorderableListView Sample'),
),
// ReorderableListView の利用
body: ReorderableListView(
// ReorderableListView のヘッダープロパティ の利用
header: const Text('header'),
padding: const EdgeInsets.symmetric(
vertical: 8.0,
horizontal: 8.0,
),
// リストのキーを設定します(再レンダリングを最適化するため)
key: const ValueKey('ReorderableListView'),
// onReorder プロパティ の利用
onReorder: (int oldIndex, int newIndex) {
taskProvider2.recorderItems(oldIndex, newIndex);
},
// リストアイテムのウィジェットを生成します
children: taskProvider2.items
.map<Widget>(
(item) => ListTile(
// 各アイテムに一意のキーを設定します
key: Key('$item'),
tileColor: item % 2 == 0 ? Colors.blue[200] : null,
title: Text('Item $item'),
leading: const Icon(Icons.work),
trailing: IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
taskProvider2.removeItems(item);
},
),
),
).toList(),
),
);
}
}
↓
2.修正箇所
・bodyに設定してあるReorderableListViewを、
Consumer<’状態管理クラス'(上記では、taskProvider2)>( builder: (context, taskProvider2, child) {
で囲み、かつ、
return ReorderableListView の様に、return で戻す。
class TaskList2 extends StatelessWidget {
const TaskList2({super.key});
// リストアイテムを生成します
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('ReorderableListView Sample'),
),
// ReorderableListView の利用
body: Consumer<TaskProvider2>(
builder:(context, taskProvider2, child){
return ReorderableListView(
// ReorderableListView のヘッダープロパティ の利用
header: const Text('header'),
padding: const EdgeInsets.symmetric(
vertical: 8.0,
horizontal: 8.0,
),
// リストのキーを設定します(再レンダリングを最適化するため)
key: const ValueKey('ReorderableListView'),
// onReorder プロパティ の利用
onReorder: (int oldIndex, int newIndex) {
taskProvider2.recorderItems(oldIndex, newIndex);
},
// リストアイテムのウィジェットを生成します
children: taskProvider2.items
.map<Widget>(
(item) => ListTile(
// 各アイテムに一意のキーを設定します
key: Key('$item'),
tileColor: item % 2 == 0 ? Colors.blue[200] : null,
title: Text('Item $item'),
leading: const Icon(Icons.work),
trailing: IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
taskProvider2.removeItems(item);
},
),
)
)
.toList(),
);
},
),
);
}
}