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

使用FutureProvider和when()方法时CircularProgressIndicator不显示的问题

问题描述

希望通过FutureProvider和when()方法在加载过程中显示CircularProgressIndicator(),目前代码中print("It works");能正常执行,但loading位置的加载指示器从未显示,是否错误使用了方法,还是需要调整其他内容?

原代码

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:cards/view/register2.dart';
import 'package:cards/view/register4.dart';
import 'package:cards/main.dart';
import 'gender.dart';
import 'header.dart';
import 'navigate.dart';
import 'style.dart';

final authFutureProvider = FutureProvider<bool>(
  (ref) async => authUser(ref),
);

class Register3Widget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final authC = ref.watch(authFutureProvider);
    Widget? loading;
    authC.when(
      data: (data) {},
      error: (error, stackTrace) {},
      loading: () {
        print("It works");//测试代码,确实能执行
        final loading = CircularProgressIndicator();
      },
    );
    final alertMessage = ref.watch(completeErrorMessage);
    return Scaffold(
        body: Padding(
      padding: const EdgeInsetsDirectional.fromSTEB(20, 75, 20, 0),
      child: Column(
        children: [
          Container(
            width: double.infinity,
            height: 50,
            alignment: Alignment.topLeft,
            child: Image.asset('images/logo.png'),
          ),
          Container(
            padding: const EdgeInsetsDirectional.fromSTEB(10, 0, 10, 0),
            margin: const EdgeInsets.only(top: 30),
            width: double.infinity,
            child: Column(
              children: [
                Align(
                  child: GenderSelect(),
                ),
                Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Align(
                        alignment: Alignment.topRight,
                        child: MyNavigator(
                          destinationTo: Register2Widget(),
                          context: context,
                          goBack: "back",
                        ),
                      ),
                      Align(
                        child: MyNavigator(
                            destinationTo: Register4Widget(),
                            context: context,
                            goBack: "Send Email"),
                      ),
                    ]),
                Align(
                  child: loading,//这里应该显示加载指示器
                ),
                Container(
                  alignment: Alignment.centerLeft,
                  child: alertMessage,
                ),
              ],
            ),
          ),
        ],
      ),
    ));
  }
}

额外尝试代码

尝试1

authC.when(
  data: (data) {},
  error: (error, stackTrace) {},
  loading: () {
    final loading = 
    WidgetsBinding.instance.addPostFrameCallback((_) {
        showDialog(
        context: context,
        builder: (context) {
          return const Center(
            child: CircularProgressIndicator(),
          );
        }
    );
    });
  },
);

尝试2

loading: () {
  final loading = 
  WidgetsBinding.instance.addPostFrameCallback((_) {
      showDialog(
      context: context,
      builder: (context) {
        return const Center(
          child: CircularProgressIndicator(),
        );
      }
  );
  Navigator.of(context).pop();
  });
},

问题原因及解决方案

核心错误

  1. 局部变量遮蔽:在loading回调里声明的final loading = CircularProgressIndicator();是局部变量,和外部的Widget? loading;没有关联,外部变量始终为null,因此不会显示任何内容。
  2. 错误使用when()方法:when()的设计初衷是返回对应状态的Widget,而非单纯执行回调逻辑。由于ConsumerWidget的build方法会在Provider状态变化时重新执行,正确做法是用when()直接生成UI,而非给外部变量赋值。

正确实现方式

直接在需要显示加载状态的位置使用authC.when(),根据不同状态返回对应Widget:

class Register3Widget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final authC = ref.watch(authFutureProvider);
    final alertMessage = ref.watch(completeErrorMessage);
    
    return Scaffold(
        body: Padding(
      padding: const EdgeInsetsDirectional.fromSTEB(20, 75, 20, 0),
      child: Column(
        children: [
          Container(
            width: double.infinity,
            height: 50,
            alignment: Alignment.topLeft,
            child: Image.asset('images/logo.png'),
          ),
          Container(
            padding: const EdgeInsetsDirectional.fromSTEB(10, 0, 10, 0),
            margin: const EdgeInsets.only(top: 30),
            width: double.infinity,
            child: Column(
              children: [
                Align(child: GenderSelect()),
                Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Align(
                        alignment: Alignment.topRight,
                        child: MyNavigator(
                          destinationTo: Register2Widget(),
                          context: context,
                          goBack: "back",
                        ),
                      ),
                      Align(
                        child: MyNavigator(
                            destinationTo: Register4Widget(),
                            context: context,
                            goBack: "Send Email"),
                      ),
                    ]),
                // 直接用when处理状态
                authC.when(
                  data: (data) => const SizedBox.shrink(), // 加载完成显示空组件
                  error: (error, stackTrace) => Text('加载失败: $error'), // 错误状态显示提示
                  loading: () => const CircularProgressIndicator(), // 加载中显示指示器
                ),
                Container(
                  alignment: Alignment.centerLeft,
                  child: alertMessage,
                ),
              ],
            ),
          ),
        ],
      ),
    ));
  }
}

对额外尝试的点评

  • 尝试1:用showDialog弹出加载框,但未在data或error状态时关闭对话框,会导致加载完成后对话框一直停留,无法交互。
  • 尝试2:在addPostFrameCallback里立刻调用Navigator.pop(),此时对话框还未完成显示就被关闭,因此看不到加载指示器,逻辑完全错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 23:20:47