我的应用程序将用户最喜欢的食物保存在SQLite数据库中。顶级小部件MyApp
使用FutureBuilder
加载此数据,然后使用Provider
将其提升到更深的位置。
有一个FoodPage
页面可以管理食物。当你"存钱"的时候在该页上,它写入SQLite。然而,MyApp
不重新加载它的未来。
FoodPage
总是通过几个Navigator.push(context, ...)
调用到达。这意味着我离顶级MyApp
跳几次,所以我不确定如何请求"re-fetch"从这里。
如果我直接在MyApp
中做我所有的工作,我可以调用setState(() {})
来刷新它的FutureBuilder。但是,我不能,因为我在一个不同的小部件。
另外,我有几个嵌套的Navigator.push
的深度,所以在这里做Navigator.pop().then(...)
并不能真正帮助我。
是我唯一的选择做笨拙的事情,并重新加载每个页面上的SQLite食品?
如果要在用户在FoodPage
中添加或更新食物后刷新顶级小部件MyApp
中的数据,则可以使用回调函数通知MyApp
数据已更改。
下面是一个如何使用回调函数实现此目的的示例:
在FoodPage
中,定义一个回调函数,该函数接受一个bool形参,指示数据是否已更改:
class FoodPage extends StatelessWidget {
final Function(bool) onDataChanged;
FoodPage({required this.onDataChanged});
// ...
void _saveFood() {
// Save the food to SQLite
// Notify the parent widget that t
he data has changed
onDataChanged(true);
}
// ...
}
在MyApp
中,将回调函数传递给FoodPage并使用它来触发数据刷新:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: _fetchData(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ChangeNotifierProvider(
create: (_) => FoodsProvider(snapshot.data),
child: CupertinoApp(
home: Center(
child: GestureDetector(
onTap: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FoodPage(
onDataChanged: (bool dataChanged) {
if (dataChanged) {
// Reload the data from SQLite
// This will trigger a rebuild of MyApp
}
},
),
),
);
},
child: const Text('Open FoodPage'),
),
),
),
);
} else {
return const CircularProgressIndicator();
}
},
);
}
}
通过将onDataChanged
回调函数传递给FoodPage
,您可以使用它在用户添加或更新食物时触发MyApp
中的数据刷新。当回调函数被调用时,您可以从SQLite
重新加载数据,这将触发MyApp
的重建并刷新UI中的数据。