我正在使用异步通知程序来运行配置的后台任务,并希望使用加载屏幕,一旦异步完成,该屏幕将被关闭并进入下一个屏幕。
这是我的代码:
异步通知器
@riverpod
class LoadingDataController extends _$LoadingDataController {
List<Activite> activites = [];
List<Devise> devises = [];
@override
FutureOr<void> build() async {
await initData();
}
Future<void> initData() async {
state = const AsyncValue.loading();
await downloadData();
await insertData();
state = const AsyncValue.data(null);
}
Future<void> downloadData() async {
devises = await ref.read(devisesRepositoryProvider).getDevises();
}
Future<void> insertData() async {
for (final devise in devises) {
await ref.read(deviseDaoProvider).insert(devise);
}
}
}
加载小部件:
class _LoadingScreenState extends ConsumerState<LoadingScreen> {
@override
void initState() {
super.initState();
// _loadData();
}
@override
Widget build(BuildContext context) {
final loadingDataAsyncValue = ref.read(loadingDataControllerProvider);
return loadingDataAsyncValue.when(
data: (_) {
log("loadingAsyncValue: DATA");
WidgetsBinding.instance.addPostFrameCallback((_) {
log('LoadingScreen::build::data: ONE');
context.go('/banks');
});
log('LoadingScreen::build:: TWO');
return Scaffold(
body: Center(),
);
},
error: (error, stackTrace) {
ref.invalidate(loadingDataControllerProvider);
log("loadingAsyncValue: ERROR: $error");
log("loadingAsyncValue: STACK: $stackTrace");
return const Center(
child: CircularProgressIndicator(),
);
},
loading: () {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SpinKitSpinningLines(
color: Colors.blue,
size: 100,
),
SizedBox(height: 20),
ListTile(
contentPadding: EdgeInsets.zero,
title: Text(
"Nous sommes entrain de configurer votre application",
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic),
textAlign: TextAlign.center,
),
subtitle: Text(
"Veuillez patienter un moment...",
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w400,
fontStyle: FontStyle.italic),
textAlign: TextAlign.center,
),
)
],
),
)
);
},
);
}
}
加载屏幕不会消失,并且永远不会调用下一个屏幕
我希望一旦异步通知器中的配置操作完成,应用程序就会进入“/banks”屏幕
虽然这可能会帮助您获得所需的内容,但此代码中还有其他内容值得调整。我建议您检查通知程序的使用情况,这样您就不会返回 void,而是正确定义您的状态。
Riverpod 中执行命令式操作(例如“路由、显示对话框、setState 等”)的正确方法是使用
ref.listen
的功能。
在您的代码中,您的
data
回调中有以下内容。这是不正确的。
WidgetsBinding.instance.addPostFrameCallback((_) {
log('LoadingScreen::build::data: ONE');
context.go('/banks');
});
您应该将构建方法设置为如下所示:
@override
Widget build(BuildContext context) {
ref.listen(loadingDataControllerProvider, (prev, next){
next.maybeWhen(
data:(_){
log('LoadingScreen::build::data: ONE');
context.go('/banks');
},
orElse:() {},
)
});
final loadingDataAsyncValue = ref.read(loadingDataControllerProvider);
... Rest of build ...
}
这将告诉您在数据步骤触发时可以路由到
/banks
页面。