flutter - Riverpod - 以更好/优雅的方式创建具有异步依赖的服务
问题描述
我已经编写了一些代码,ApiService
为StateNotifier
. ApiService
依赖于-authenticatorclient
身份验证客户端必须异步创建,因为它使用 sharedprefs 来获取令牌。
我只是想弄清楚他们的写作方式是否更优雅。基本上,当服务 apiService 被注入到 StateNotifier 中时,它可能是可以为空的......对我来说,这有点代码味道。
所以简而言之,这就是我正在做的事情......使用 aFutureProvider
来实例化RestClient
aDio
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();
}
...
}
对上述方法有什么想法吗?
谢谢
解决方案
解决此问题的一种方法是在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);
});
推荐阅读
- sql - 获取分组中最新日期的行
- android - 为什么 EGL 上下文只与一个线程相关
- python - 遍历一个字符串,需要该字符串的索引
- elasticsearch - Elasticsearch Opendistro 安全性——将用户添加到 readall 角色
- google-maps - 如何在谷歌地图中绘制一个位于道路图层下方的形状?
- html - 如何在网站上实时显示对 textarea 的更改
- javascript - Javascript:使用 Promise 链接 axios 调用
- c# - 将 System.Drawing.Icon 转换为 SkiaSharp.SKBitmap
- oracle - ADD_MASTER_DATABASE 程序更改 tns 登录用户名
- c++ - 配置认为CPP有问题