如何在Flutter with Riverpod中刷新FutureProvider而不再次显示加载指示器?

1sbrub3j  于 2022-12-14  发布在  Flutter
关注(0)|答案(2)|浏览(185)

目前,我正在刷新FutureProvider,它负责从Firebase获取数据,并使用liquid_pull_to_refresh包将其显示在简单的ListView中,这会导致列表消失,加载指示符再次显示,最后列表再次显示。
我想实现的是保持列表的显示,并且只在获取完成后更新它。
提供者:

final userProfileProvider = FutureProvider.family<FullUserModel?, String?>((ref, value) => ref.read(databaseServiceProvider).getFullUserModel(value));

刷新部件:

LiquidPullToRefresh(
  onRefresh: () async {
    ref.refresh(userProfileProvider(uid));
  },
  child: ListView()
)

有什么好办法吗?

odopli94

odopli941#

这不再是一个问题,因为Riverpod 2.0+有新的刷新行为。它现在在加载时返回以前的数据/错误值。
在提供者发出AsyncValue.data或AsyncValue.error之后,该提供者将不再发出AsyncValue. loading。相反地,它会重新发出最新的值,但属性AsyncValue.isRefreshing为true。

这可让UI在重新整理提供者时,继续显示先前的数据/错误。

来源

vc9ivgsu

vc9ivgsu2#

不确定这是一个好的方法,但我已经做了一个例子,我已经这样做:
小工具:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          body: Center(
        child: TimeDisplayer(),
      )),
    );
  }
}

class TimeDisplayer extends ConsumerWidget{
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final time = ref.watch(ref.watch(diplayedTimer));

    return Column(
      children: [
        time.when(data: (data)=>Text(data.toString()), error: (e,_)=>Text(e.toString()), loading: ()=>CircularProgressIndicator()),
        IconButton(onPressed: ()=>ref.refresh(timeRefreshProvider), icon: Icon(Icons.refresh))
      ],
    );
  }
}

提供者:

final timeRefreshProvider = FutureProvider<DateTime>((ref) async {
  await Future.delayed(const Duration(seconds: 1));
  return DateTime.now();
});

final diplayedTimer = Provider<StateProvider<AsyncValue<DateTime>>>((ref) {
  final _diplayedTimer = StateProvider<AsyncValue<DateTime>>((ref) {
    return const AsyncLoading();
  });
  ref.listen(timeRefreshProvider, (previous, next) {
    if (next is AsyncData<DateTime>) {
      ref.read(_diplayedTimer.state).update((state) => next);
    }
  });
  return _diplayedTimer;
});

相关问题