flutter中的Riverpode和Hooks,如何实现异步调用的StateNotifier?
Riverpode and Hooks in flutter, how to implement the StateNotifier for async calls?
我是 flutter 的新手,最近我决定研究提供程序,以便能够重用我使用的一些 sqlite 数据库调用 。
阅读后我开始使用 riverpod_hooks 但我卡住了。
目前我有一个供应商可以从 sqlite 获取数据:
final bloodPressureProvider = FutureProvider((_) => _findAllBloodPressures());
Future<List<BloodPressure>> _findAllBloodPressures() async {
var _bloodPressure = BloodPressure.forSearchOnly();
var result = await _bloodPressure.findAll();
return result;
}
我可以成功地使用它来呈现图表并显示列表:
class BloodPressureList extends HookWidget {
@override
Widget build(BuildContext context) {
final bpList = useProvider(bloodPressureProvider);
return Scaffold(
drawer: NutriDrawer(context).drawer(),
appBar: AppBar(
title: Text('Blood Pressure History'),
),
body: Column(
children: [
Container(
padding: EdgeInsets.fromLTRB(0, 25, 15, 5),
child: bpList.when(
data: (bloodPressureList) => _buildLineChart(bloodPressureList),
loading: () => CircularProgressIndicator(),
error: (_, __) => Text('Ooooopsss error'),
),
),
Expanded(
child: bpList.when(
data: (bloodPressureList) => _getSlidableListView(bloodPressureList, context),
loading: () => CircularProgressIndicator(),
error: (_, __) => Text('Ooopsss error'),
),
),
],
), ...
我目前遇到的问题是,每当将新元素添加到数据库中时,都会向小部件发出通知,这是在另一个 screen/widget 中完成的,在使用提供程序之前,我会使用 setState 但现在我明白了我应该可能实现一个 StateNotifier,但我缺少将其与从上面提供程序片段中使用的数据库返回的异步调用集成的正确方法。
非常感谢任何正确方向的指示。
更新解决方案: 根据下面接受的答案,我使用了 context.refresh,它完全符合我的要求:
var result = Navigator.push(context, MaterialPageRoute(builder: (context) {
return BloodPressureDetail(title, bloodPressure);
}));
result.then((_) => context.refresh(bloodPressureProvider));
因此,当从 edit/add 屏幕导航回来时,提供商上下文会刷新,图表和列表的状态会自动更新。
默认情况下,FutureProvider 会缓存未来的结果,因此只会在第一次访问时获取它。
如果您想在每次转到屏幕时都获得一个新值,请使用 FutureProvider.autoDispose。
如果你想手动刷新提供者,你可以使用 context.refresh(bloodPressureProvider) 和 FutureProvider。
如果您不想访问您的数据库以获取值,但仍希望同步屏幕,您可以实现一个代表您的数据库状态的 stateNotifier
final dbState =
StateNotifierProvider<dbState>((ProviderReference ref) {
final dbState = DbState();
dbState.init();
return dbState;
});
class dbState extends StateNotifier<AsyncValue<List<String>>> {
/// when the constructor is called the initial state is loading
dbState() : super(AsyncLoading<List<String>>());
/// fetch the values from the database and set the state to AsyncData
///(could be good to add a try catch and set the sate to an error if one
/// occurs)
void init()async{
state = AsyncLoading<List<String>>();
final fetchedValues = await fetchValues();
state = AsyncData<List<String>>(fetchedValues);
}
}
我是 flutter 的新手,最近我决定研究提供程序,以便能够重用我使用的一些 sqlite 数据库调用
阅读后我开始使用 riverpod_hooks 但我卡住了。
目前我有一个供应商可以从 sqlite 获取数据:
final bloodPressureProvider = FutureProvider((_) => _findAllBloodPressures());
Future<List<BloodPressure>> _findAllBloodPressures() async {
var _bloodPressure = BloodPressure.forSearchOnly();
var result = await _bloodPressure.findAll();
return result;
}
我可以成功地使用它来呈现图表并显示列表:
class BloodPressureList extends HookWidget {
@override
Widget build(BuildContext context) {
final bpList = useProvider(bloodPressureProvider);
return Scaffold(
drawer: NutriDrawer(context).drawer(),
appBar: AppBar(
title: Text('Blood Pressure History'),
),
body: Column(
children: [
Container(
padding: EdgeInsets.fromLTRB(0, 25, 15, 5),
child: bpList.when(
data: (bloodPressureList) => _buildLineChart(bloodPressureList),
loading: () => CircularProgressIndicator(),
error: (_, __) => Text('Ooooopsss error'),
),
),
Expanded(
child: bpList.when(
data: (bloodPressureList) => _getSlidableListView(bloodPressureList, context),
loading: () => CircularProgressIndicator(),
error: (_, __) => Text('Ooopsss error'),
),
),
],
), ...
我目前遇到的问题是,每当将新元素添加到数据库中时,都会向小部件发出通知,这是在另一个 screen/widget 中完成的,在使用提供程序之前,我会使用 setState 但现在我明白了我应该可能实现一个 StateNotifier,但我缺少将其与从上面提供程序片段中使用的数据库返回的异步调用集成的正确方法。
非常感谢任何正确方向的指示。
更新解决方案: 根据下面接受的答案,我使用了 context.refresh,它完全符合我的要求:
var result = Navigator.push(context, MaterialPageRoute(builder: (context) {
return BloodPressureDetail(title, bloodPressure);
}));
result.then((_) => context.refresh(bloodPressureProvider));
因此,当从 edit/add 屏幕导航回来时,提供商上下文会刷新,图表和列表的状态会自动更新。
默认情况下,FutureProvider 会缓存未来的结果,因此只会在第一次访问时获取它。 如果您想在每次转到屏幕时都获得一个新值,请使用 FutureProvider.autoDispose。 如果你想手动刷新提供者,你可以使用 context.refresh(bloodPressureProvider) 和 FutureProvider。
如果您不想访问您的数据库以获取值,但仍希望同步屏幕,您可以实现一个代表您的数据库状态的 stateNotifier
final dbState =
StateNotifierProvider<dbState>((ProviderReference ref) {
final dbState = DbState();
dbState.init();
return dbState;
});
class dbState extends StateNotifier<AsyncValue<List<String>>> {
/// when the constructor is called the initial state is loading
dbState() : super(AsyncLoading<List<String>>());
/// fetch the values from the database and set the state to AsyncData
///(could be good to add a try catch and set the sate to an error if one
/// occurs)
void init()async{
state = AsyncLoading<List<String>>();
final fetchedValues = await fetchValues();
state = AsyncData<List<String>>(fetchedValues);
}
}