flutter - flutter中的Riverpode和Hooks,如何实现异步调用的StateNotifier?

标签 flutter riverpod flutter-hooks

我是 flutter 新手,最近我决定研究提供程序,以便能够重用我使用 FutureBuilder as suggested in this other question 的一些 sqlite DB 调用.

阅读完相关内容后,我开始使用 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'),
            ),
          ),
        ],
      ), ...

我目前遇到的问题是,每当将新元素添加到数据库中(在另一个屏幕/小部件中完成)时,都会向小部件发出通知,在使用提供程序之前我会使用 setState 但现在我知道我应该实现一个可能StateNotifier,但我缺少将其与上面提供程序片段中使用的数据库返回的异步调用集成的正确方法。

非常感谢任何正确方向的指点。

更新解决方案:根据下面接受的答案,我使用了 context.refresh,它完全符合我的要求:

var result = Navigator.push(context, MaterialPageRoute(builder: (context) {
      return BloodPressureDetail(title, bloodPressure);
    }));
    result.then((_) => context.refresh(bloodPressureProvider));

因此,当从编辑/添加屏幕返回时,提供程序上下文会刷新,图表和列表的状态也会自动更新。

最佳答案

默认情况下,FutureProvider 会缓存 future 的结果,因此仅在第一次访问时才获取它。 如果您想在每次进入屏幕时获取新值,请使用 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 - flutter中的Riverpode和Hooks,如何实现异步调用的StateNotifier?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66504991/

相关文章:

flutter - 参数类型 'List<Series<dynamic, dynamic>>' 不能分配给参数类型 'List<Series<dynamic, String>>

构建方法中的 Flutter Riverpod context.read vs Provider

flutter - 使用 flutter HookWidget 和 didChangeAppLifecycleState

php - 在flutter中获取JSON数据将返回NULL

flutter - Flutter:使用badCertificateCallback进行HTTPS证书验证

Flutter 必填关键字

flutter - 使用继承的小部件传递小部件 key

Flutter Hooks 使用 useEffect 获取数据 - setState() 或 markNeedsBuild() 在构建期间调用

flutter - 使用导航和堆栈将多个页面实现为单个页面