首页 > 解决方案 > Riverpod - 以更好/优雅的方式创建具有异步依赖的服务

问题描述

我已经编写了一些代码,ApiServiceStateNotifier. ApiService依赖于-authenticatorclient身份验证客户端必须异步创建,因为它使用 sharedprefs 来获取令牌。

我只是想弄清楚他们的写作方式是否更优雅。基本上,当服务 apiService 被注入到 StateNotifier 中时,它可能是可以为空的......对我来说,这有点代码味道。

所以简而言之,这就是我正在做的事情......使用 aFutureProvider来实例化RestClientaDio

authenticatorClient = FutureProvider<RestClient>((ref) async {
  final prefs = await SharedPreferences.getInstance();
  final dio = Dio();
  ...
  return RestClient(dio);
}

然后我观看并使用 MaybeWhen 来返回服务

final clientCreatorWatchProvider = Provider<ApiService?>((ref) => ref
    .watch(authenticatorClient)
    .whenData((value) => ApiService(value))
    .maybeWhen(
      data: (service) => service,
      orElse: () => null,
    ));

所以我不喜欢的是 orElse 返回 null

然后我StateNotifier在看...

final AppState = StateNotifierProvider<AppNotifier, String>(
    (ref) => AppNotifier(ref.watch(clientCreatorWatchProvider)));

class AppNotifier extends StateNotifier<String> {
  final ApiService? apiService;

  AppNotifier(this.apiService) : super("loading") {
    init();
  }
...
}

对上述方法有什么想法吗?

谢谢

标签: flutterriverpod

解决方案


解决此问题的一种方法是在SharedPreferences提供程序之外进行初始化。然后,您可以使用ProviderScope覆盖同步提供程序,从而无需使用AsyncValue.

初始化应用程序时,请执行以下操作:

final sharedPreferences = Provider<SharedPreferences>((_) => throw UnimplementedError());

Future<void> main() async {
  final sharedPrefs = await SharedPreferences.getInstance();

  runApp(
    ProviderScope(
      overrides: [
        sharedPreferences.overrideWithValue(sharedPrefs),
      ],
      child: MyApp(),
    ),
  );
}

现在您可以像这样编写您的提供程序:

final authenticatorClient = Provider<RestClient>((ref) {
  final prefs = ref.watch(sharedPreferences);
  final dio = Dio();
  ...
  return RestClient(dio);
}

final clientCreatorWatchProvider = Provider<ApiService>((ref) {
  final authClient = ref.watch(authenticatorClient);
  return ApiService(authClient);
});

推荐阅读