如何使用 ref.listen 对 Riverpod FutureProvider 做出反应?

问题描述 投票:0回答:3
final nextRouteProvider = FutureProvider<String>((ref) async {
  await Future.delayed(const Duration(seconds: 3));
  bool isAppFreshInstall = StorageManager.instance.isAppFreshInstall();
  if (isAppFreshInstall) {
    return AppRouter.onBoardingPath;
  } else {
    return AppRouter.loginPath;
  }
});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    ref.listen<Future<String>>(nextRouteProvider.future, (_, Future<String> path) async {
      context.go(await path);
    });

    return SplashScreen();
  }

上面的逻辑不起作用,但它与 StateNotifierProvider 配合得很好。

class RootViewNotifier extends StateNotifier<String> {
  RootViewNotifier() : super('/') {
    decideRootView();
  }

  void decideRootView() async {
    await Future.delayed(const Duration(seconds: 3));
    var storageManager = StorageManager.instance;
    if (storageManager.isAppFreshInstall()) {
      state = AppRouter.onBoardingPath;
    } else {
      state = AppRouter.loginPath;
    }
  }
}

final rootViewNotifierProvider =
    StateNotifierProvider<RootViewNotifier, String>(() => RootViewNotifier());

@override
  Widget build(BuildContext context, WidgetRef ref) {
    ref.listen<String>(rootViewNotifierProvider, (, String path) {
      context.go(path);
    });

   return SplashScreen(); 
 }

但是更好的方法是使用 FutureProvider,在这种情况下它不起作用。那么我的代码有什么问题。我如何以相同的逻辑使用FutureProvider?

flutter riverpod
3个回答
3
投票

nextRouteProvider
而不是
nextRouteProvider.future

像这样:

ref.listen(
  nextRouteProvider,
  (AsyncValue<String>? _, AsyncValue<String> next) {
      context.go(next.asData!.value);
   },
);

0
投票

未来的提供程序不旨在用于通知更改。它仅用于通知异步源的数据准备就绪。相反,要获得通知,唯一的解决方案是通知程序提供程序,并将其与异步数据一起使用:

Future<int> fetch() aynsc => 42;
class Whatever extends StateNotifier<AsyncValue<int>> {    
    Whatever(): super(const AsyncValue.loading()) {        
        _fetch();
    }
    Future<void> _fetch() async {
        state = const AsyncValue.loading();
        state = await AsyncValue.guard(() => fetch());    
    }
}

0
投票

不再建议将 StateNotifier 与 Riverpod 一起使用。更正确的示例是使用 AsyncNotifier,它提供 AsyncValue 以及 ref.watch 或 ref.listen 的用法。下面的示例和更多信息请参见 从 StateNotifier 迁移 Riverpod 文档

Future<int> fetch() async => 42;

class MyAsyncNotifier extends AsyncNotifier<int> {   
  static final provider =
  AsyncNotifierProvider<MyAsyncNotifier, int>(MyAsyncNotifier); 

  @override
  FutureOr<int> build() async {
     return fetch();
  }
}

然后您可以使用以下代码在小部件中收听此通知程序。

class MyWidget extends ConsumerStatefulWidget {
   const MyWidget({super.key});

     @override
     ConsumerState< MyWidget > createState() => _ MyWidgetState();
}

class _MyWidgetState extends ConsumerState<MyWidget>{
    @override
    Widget build(BuildContext context) {
      ref.listen(MyAsyncNotifier.provider, (previous, next){
          next.whenData((value) {
            //do something with value
          }
      });
   }
 }
© www.soinside.com 2019 - 2024. All rights reserved.