使用 asyncnotifier 调用 api 并将值存储到数据库时,无法使用 go_router 的 context.go 进入下一个屏幕

问题描述 投票:0回答:1

我正在使用异步通知程序来运行配置的后台任务,并希望使用加载屏幕,一旦异步完成,该屏幕将被关闭并进入下一个屏幕。

这是我的代码:

异步通知器

@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”屏幕

flutter riverpod flutter-go-router
1个回答
0
投票

虽然这可能会帮助您获得所需的内容,但此代码中还有其他内容值得调整。我建议您检查通知程序的使用情况,这样您就不会返回 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
页面。

© www.soinside.com 2019 - 2024. All rights reserved.