如何使用动态加载的异步数据设置多个 StateNotifierProvider?
我完全被下面的任务困住了。 来解决这些步骤
- 因此,我们的想法是使用
Riverpod
在暂停应用程序时使用某种
Future async
从数据库获取数据 (显示SomeLoadingPage()
等) 数据加载后:
2.1 初始化多个全局
StateNotifierProvider
,这些全局StateNotifierProvider
使用其构造函数中的数据,并且可以通过更新其状态的方法进一步在整个应用程序中使用。2.2 然后显示
MainScreen()
和 UI 的其余部分
到目前为止,我已经尝试过类似的操作:
class UserData extends StateNotifier<AsyncValue<Map>> { // just <Map> for now, for simplicity
UserData() : super(const AsyncValue.loading()) {
init();
}
Future<void> init() async {
state = const AsyncValue.loading();
try {
final HttpsCallableResult response =
await FirebaseFunctions.instance.httpsCallable('getUserData').call();
state = AsyncValue.data(response.data as Map<String, dynamic>);
} catch (e) {
state = AsyncValue.error(e);
}}}
final userDataProvider = StateNotifierProvider<UserData, AsyncValue<Map>>((ref) => UserData());
final loadingAppDataProvider = FutureProvider<bool>((ref) async {
final userData = await ref.watch(userDataProvider.future);
return userData.isNotEmpty;
});
class LoadingPage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return FutureBuilder(
future: ref.watch(loadingAppDataProvider.future),
builder: (ctx, AsyncSnapshot snap) {
// everything here is simplified for the sake of a question
final Widget toReturn;
if (snap.connectionState == ConnectionState.waiting) {
toReturn = const SomeLoadingPage();
} else {
snap.error != null
? toReturn = Text(snap.error.toString())
: toReturn = const SafeArea(child: MainPage());
}
return toReturn;},);}}
我有意使用 FutureBuilder
而不是 .when() 因为将来我可能打算将
Future.wait([])
与多个 future 一起使用
到目前为止,这有效,但是当我想在 < 内部实现某种 update() 方法时,麻烦就来了code>UserData 并收听它的变量贯穿整个应用程序。 之类的内容
late Map userData = state.value ?? {};
late Map<String, dynamic> settings = userData['settings'] as Map<String, dynamic>;
void changeLang(String lang) {
print('change');
for (final key in settings.keys) {
if (key == 'lang') settings[key] = lang;
state = state.whenData((data) => {...data});
}
}
诸如SomeLoadingPage()
会出现在每个 changeLang()
方法调用上。简而言之: 我真的希望有几个 StateNotifierProvider 能够从内部修改其状态并从外部监听它。但是从数据库中获取初始状态,并使整个应用程序等待获取此数据并初始化这些提供程序。
I'm completely stuck with the task below.
So, the idea is to solve these steps using Riverpod
Fetch data from db with some kind of
Future async
while pausing the app (displaySomeLoadingPage()
etc.)Once the data has loaded:
2.1 initialize multiple global
StateNotifierProvider
s which utilize the data in their constructors and can further be used throughout the app with methods to update their states.2.2 then show
MainScreen()
and the rest of UI
So far I've tried something like this:
class UserData extends StateNotifier<AsyncValue<Map>> { // just <Map> for now, for simplicity
UserData() : super(const AsyncValue.loading()) {
init();
}
Future<void> init() async {
state = const AsyncValue.loading();
try {
final HttpsCallableResult response =
await FirebaseFunctions.instance.httpsCallable('getUserData').call();
state = AsyncValue.data(response.data as Map<String, dynamic>);
} catch (e) {
state = AsyncValue.error(e);
}}}
final userDataProvider = StateNotifierProvider<UserData, AsyncValue<Map>>((ref) => UserData());
final loadingAppDataProvider = FutureProvider<bool>((ref) async {
final userData = await ref.watch(userDataProvider.future);
return userData.isNotEmpty;
});
class LoadingPage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return FutureBuilder(
future: ref.watch(loadingAppDataProvider.future),
builder: (ctx, AsyncSnapshot snap) {
// everything here is simplified for the sake of a question
final Widget toReturn;
if (snap.connectionState == ConnectionState.waiting) {
toReturn = const SomeLoadingPage();
} else {
snap.error != null
? toReturn = Text(snap.error.toString())
: toReturn = const SafeArea(child: MainPage());
}
return toReturn;},);}}
I intentionally use FutureBuilder
and not .when()
because in future i may intend to use Future.wait([])
with multiple futures
This works so far, but the troubles come when I want to implement some kind of update() methods inside UserData
and listen to its variables through the entire app. Something like
late Map userData = state.value ?? {};
late Map<String, dynamic> settings = userData['settings'] as Map<String, dynamic>;
void changeLang(String lang) {
print('change');
for (final key in settings.keys) {
if (key == 'lang') settings[key] = lang;
state = state.whenData((data) => {...data});
}
}
SomeLoadingPage()
appears on each changeLang()
method call.
In short:
I really want to have several StateNotifierProvider
s with the ability to modify their state from the inside and listen to it from outside. But fetch the initial state from database and make the intire app wait for this data to be fetched and these providers to be initilized.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
所以,我想我想出了如何解决这个问题:
这对我有用,至少在这个复杂程度上是这样。
如果有更好的建议,我将保留未解决的问题。
So, I guess I figured how to solve this:
This works for me, at least on this level of complexity.
I'll leave question unsolved in case there are some better suggestions.