我找不到一个令人满意的方法来触发孙子部件的祖父状态变化。我的应用程序保存和来源的数据都来自一个设备上的数据库。我试图进行这么远没有使用状态管理库,因为我认为这是矫枉过正-应用程序并不复杂。
我有一个ListView
(grandparent),它又有我自己的ListTiles
版本的子项。每个ListTile
上有两个图标按钮,一个用于编辑,一个用于删除-这两个按钮都触发不同的alertdialog
(孙)弹出窗口。当我对数据执行更新或删除时,它被写入数据库并返回Future
-然后我需要祖父ListView
状态来刷新。StatefulBuilders
只给予刷新孙节点状态的方法(与子对象分开),而不是触发“多级别”状态更改的方法。
是时候采用BLOC或Riverpod等状态管理解决方案了,还是有其他解决方案?
ListView
祖父级小部件
@override
Widget build(BuildContext context) {
return Scaffold(
body: Builder(
builder: (BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// other children here
Expanded(
flex: 11,
child: FutureBuilder<List<MyCustomObject>>(
future: _getQuotes(), // queries the db
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.waiting
&& !snapshot.hasData) {
return const Center(
child: SizedBox(
height: AppDims.smallSizedBoxLoadingProgress,
width: AppDims.smallSizedBoxLoadingProgress,
child: CircularProgressIndicator()
),
);
} else if (snapshot.hasError) {
log(snapshot.error.toString());
log(snapshot.stackTrace.toString());
return Center(child: Text(snapshot.error.toString()));
} else {
// no point using StatefulBuilder here, as i need
// to potentially trigger _getQuotes() again to rebuild the entire ListView
return ListView.builder(
padding: const EdgeInsets.symmetric(
horizontal: AppDims.textHorizontalPadding,
vertical: AppDims.textVerticalPadding
),
itemCount: snapshot.data!.length,
itemBuilder: (context, int index) {
return MyCustomTile(
// tile data mapping from snapshot for MyCustomObject
);
},
);
}
},
)
)
]
);
}
)
);
}
MyCustomTile
子部件
@override
Widget build(BuildContext context) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppDims.tileBorderRadius),
side: const BorderSide(
color: Colors.green,
width: 1.5,
)
),
child: ListTile(
// other omitted ListTile params here
trailing: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: const Icon(Icons.edit),
onPressed: () => showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return EditDialog();
}
).then((_) => setState(() {})), // will only setState on the dialog!
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () => showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context) => DeleteWarningDialog(
widget.id,
AppStrings.price.toLowerCase(),
true
),
),
),
]
),
),
);
}
DeleteWarningDialog
孙小部件
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text(_buildFinalWarningString()),
actions: [
TextButton(
child: const Text(AppStrings.cancel),
onPressed: () => Navigator.pop(context),
),
TextButton(
child: const Text(AppStrings.delete),
onPressed: () {
_appDatabase.deleteFoo(widget.objectIdToDelete);
Navigator.pop(context);
},
)
],
);
}
2条答案
按热度按时间whlutmcx1#
您可以创建一个更新祖父小部件的
state
的函数,并将其从祖父传递到父,然后从父传递到孙,并在您想要更新祖父widget
的任何地方使用它arknldoa2#
你必须在grandParent中声明一个函数,在你的例子中就是listView,然后把它传递给parent和children。但是这会很复杂,效率也不高,使用状态管理会使它变得简单和干净