You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AsyncNotifier调用API存数据时,GoRouter的context.go无法跳转页面

问题分析与解决方案

核心问题

加载页面无法跳转的根本原因是使用了ref.read而非ref.watch监听状态:

  • ref.read仅获取当前状态一次,不会监听后续的状态变化;当AsyncNotifier的状态从loading变为data时,组件不会触发重建,自然不会执行data分支的跳转逻辑。

修复步骤及代码优化

1. 优化AsyncNotifier代码

利用Riverpod自动管理AsyncValue状态,移除手动设置state的冗余代码:

@riverpod
class LoadingDataController extends _$LoadingDataController {
  List<Activite> activites = [];
  List<Devise> devises = [];

  @override
  Future<void> build() async {
    // Riverpod会自动将state设为loading,无需手动设置
    await downloadData();
    await insertData();
    // 执行完成后自动切换为data状态
  }

  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);
    }
  }
}

2. 修改加载组件的状态监听逻辑

将ref.read替换为ref.watch,并添加防重复跳转的标志位:

class _LoadingScreenState extends ConsumerState<LoadingScreen> {
  bool _hasNavigated = false; // 防止重复触发跳转

  @override
  Widget build(BuildContext context) {
    // 使用watch监听状态变化,状态更新时自动重建组件
    final loadingDataAsyncValue = ref.watch(loadingDataControllerProvider);

    return loadingDataAsyncValue.when(
      data: (_) {
        if (!_hasNavigated) {
          _hasNavigated = true;
          // 延迟跳转确保组件渲染完成
          WidgetsBinding.instance.addPostFrameCallback((_) {
            context.go('/banks');
          });
        }
        return const Scaffold(body: Center());
      },
      error: (error, stackTrace) {
        log("加载出错: $error");
        log("堆栈信息: $stackTrace");
        return Scaffold(
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text("加载失败,请重试"),
                ElevatedButton(
                  onPressed: () => ref.invalidate(loadingDataControllerProvider),
                  child: const Text("重试"),
                ),
              ],
            ),
          ),
        );
      },
      loading: () {
        return Scaffold(
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                SpinKitSpinningLines(
                  color: Colors.blue,
                  size: 100,
                ),
                const SizedBox(height: 20),
                const 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,
                  ),
                )
              ],
            ),
          ),
        );
      },
    );
  }
}

关键说明

  • ref.watch会持续监听状态变化,当AsyncNotifier的任务完成后,组件会自动重建并进入data分支执行跳转。
  • _hasNavigated标志位避免了组件因状态重复更新而多次触发跳转的问题。
  • AsyncNotifier的build方法为异步函数时,Riverpod会自动管理loading/data/error三种状态,无需手动设置state。

内容的提问来源于stack exchange,提问作者Armando Sudi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 15:36:10