在不显示加载程序的情况下刷新 FutureProvider

Refresh FutureProvider without showing loader

我有一个钱包提供商,它使用未来提供商从服务器获取钱包余额,一切正常,我遇到的唯一问题是刷新钱包提供商以使用 context.refresh(walletProvider)。这很好用,但我不希望加载小部件在它尝试从服务器获取新数据时显示,而是应该显示旧数据,直到新数据从服务器返回。

代码如下:

final walletProvider =
    FutureProvider<WalletModel>((ref) => WalletService().fetchWalletBalance());
Consumer(builder: (context, watch, child) {
final wallet = watch(walletProvider);


return Column(
 children: [
  wallet.when(
   data: (value) {
   return walletContainer(
  context: context, walletModel: value);
},
  loading: () => walletLoading(),
   error: (err, stack) {
  return Text(
'${err.toString()}',
 },
)
],
),

然后我从一个按钮调用 context.refresh(walletProvider);,它刷新但显示加载程序小部件,这不是我想要的。我希望在刷新过程中显示之前的数据。

请问如何实现这个?

将来可能会有更好的解决方案 (see this issue)。

不过,与此同时,我想出了一个应该会产生您想要的行为的解决方案。

final myFutureProvider = FutureProvider.autoDispose<List<int>>((ref) async {
  return Future.delayed(
    const Duration(seconds: 2),
    () => List<int>.generate(100, (_) => Random().nextInt(1000)),
  );
});

final cachedProvider = StateProvider.autoDispose<List<int>>((ref) => []);

class ExampleListView extends StatelessWidget {
  const ExampleListView({Key? key, required this.data}) : super(key: key);

  final List<int> data;

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: data.length,
      itemBuilder: (context, index) => ListTile(title: Text(data[index].toString())),
    );
  }
}

class Refresher extends ConsumerWidget {
  const Refresher({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, ScopedReader watch) {
    return RefreshIndicator(
      onRefresh: () async {
        await context.refresh(myFutureProvider);
      },
      child: watch(myFutureProvider).when(
        loading: () {
          final cachedData = watch(cachedProvider).state;
          return cachedData.isNotEmpty
              ? ExampleListView(data: cachedData)
              : Center(child: CircularProgressIndicator());
        },
        error: (e, s) => Text(''),
        data: (data) {
          WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
            watch(cachedProvider).state = data;
          });
          return ExampleListView(data: data);
        },
      ),
    );
  }
}

本质上,我们将以前的数据保存到 StateProvider 中,以便我们可以在加载新数据时继续显示以前的数据。我将此示例设为通用示例,因此它处于准备就绪状态,您可以在将其应用到您的代码之前进行试用。