Search code examples
flutterdartflutter-riverpod

How to display CircularProgressIndicator() with FutureBuilder?


I'm very new about async and await in Dart & Flutter and want to use CircularProgressIndicator() in certain place during loading.

please refer to my shorten code below.

  1. I want to show CircularProgressIndicator() at the place // here1 should be displayed
  2. And learned, I can use Future builder to display the ProgressIndicator during asynchronous communication working.
  3. asynchronous communication is happening at the place here here3 // asynchronous communication happens.
  4. Finally, the value returned by asynchronous communication is used here // here 2 Future Object

I could not understand what should I define at future property in Future Builder in this case , and finally could not get it worked.

I do appreciate for your helpful comment, thanks.

//register3.dart
;import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:cards/view/register4.dart';
import 'navigate.dart';

class Register3Widget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {

    return Scaffold(
      body: Padding(
      padding: const EdgeInsetsDirectional.fromSTEB(20, 75, 20, 0),
      child: Column(
        children: [
          Container(
            padding: const EdgeInsetsDirectional.fromSTEB(10, 0, 10, 0),
            margin: const EdgeInsets.only(top: 30),
            width: double.infinity,
            child: Column(
              children: [
                Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Align(
                        child: MyNavigator(
                            destinationTo: Register4Widget(),
                            context: context,
                            goBack: "send email"),
                      ),
                    ]),
                Container(// here1 should be displayed 
                  child: FutureBuilder(
                    builder: (context, snapshot) {
                      if (snapshot.connectionState == ConnectionState.waiting) {
                        return Center(
                          child: CircularProgressIndicator(),
                        );
                      }else{
                        return SizedBox.shrink();
                      }
                    },
                  ),
                )
              ],
            ),
          ),
        ],
      ),
    ));
  }
}
//navigate.dart
import 'package:cards/control/auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'style.dart';

class MyNavigator extends ConsumerWidget {
  final Widget destinationTo;
  final BuildContext context;
  final String goBack;
  final List<GlobalKey<FormState>>? formKeyList;

  MyNavigator(
      {required this.destinationTo,
      required this.context,
      required this.goBack,
      this.formKeyList,
      Key? key,
      required})
      : super(key: key) {
    // print(destinationTo.runtimeType);
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // TextButton myNavigator(BuildContext context) {
    return TextButton(
      style: TextButton.styleFrom(
        foregroundColor: MyStyle.mainColor,
      ),
      onPressed: () {
        switch (goBack) {
          case "send email":
            final getResult = authUser(ref);// here 2 Future Object
            getResult.then((value) {
              if (value == false) {
                return;
              } else if (value == true) {
                navigatorAnimation(context: context,goBack: goBack,destinationTo: destinationTo);
              }
            });
            break;
        }
      },
      child: Text(goBack),
    );
  }
}

void navigatorAnimation(
    {required BuildContext context,
    required String goBack,
    required Widget destinationTo}) {
  Offset? begin;
  Navigator.of(context).push(
    PageRouteBuilder(
      pageBuilder: (context, animation, secondaryAnimation) {
        return destinationTo;
      },
      transitionDuration: const Duration(milliseconds: 300),
      transitionsBuilder: (context, animation, secondaryAnimation, child) {
        goBack == "send email" ? begin = const Offset(1.0, 0.0) : 0;
        const Offset end = Offset.zero;
        final Animatable<Offset> tween = Tween(begin: begin, end: end)
            .chain(CurveTween(curve: Curves.easeInOut));
        final Animation<Offset> offsetAnimation = animation.drive(tween);
        return SlideTransition(
          position: offsetAnimation,
          child: child,
        );
      },
    ),
  );
}
auth.dart
import 'package:firebase_auth/firebase_auth.dart';
import '../main.dart';
Future<bool> authUser(ref) async { here3 // asynchronous communication happens
        try {
          final FirebaseAuth auth = FirebaseAuth.instance;
          final UserCredential _result =
            await auth.createUserWithEmailAndPassword(
            email: emailController.text,
            password: maskController.text,
          );
           User _user = _result.user!;
           _user.sendEmailVerification();
           return Future<bool>.value(true);
        } on FirebaseAuthException catch (e) {
          //error handling
          return Future<bool>.value(false);
        }
}

Renewal code:

Future<bool> authUser(ref) async {
        try {
          final FirebaseAuth auth = FirebaseAuth.instance;
          final UserCredential _result =
            await auth.createUserWithEmailAndPassword(
            email: emailController.text,
            password: maskController.text,
          );
           User _user = _result.user!; 
           _user.sendEmailVerification();
           return true;
        } on FirebaseAuthException catch (e) {
 //error handling
 return false;
        }
}

//navigator.dart
final authProvider = FutureProvider<bool>(
  (ref) async => authUser(ref),
);//defined globally

class MyNavigator extends ConsumerWidget {
  final Widget destinationTo;
  final BuildContext context;
  final String goBack;
  final List<GlobalKey<FormState>>? formKeyList;

  MyNavigator(
      {required this.destinationTo,
      required this.context,
      required this.goBack,
      this.formKeyList,
      Key? key,
      required})
      : super(key: key) {
    // print(destinationTo.runtimeType);
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final authC = ref.watch(authProvider);
    // TextButton myNavigator(BuildContext context) {
    return TextButton(
      style: TextButton.styleFrom(
        foregroundColor: MyStyle.mainColor,
      ),
      onPressed: () {
        switch (goBack) {
          case "send email":
          // ref.refresh(authProvider);
          authC.when(
            data: (data) => print(data),
            error: (error, stackTrace) => print(error),
            loading: () => CircularProgressIndicator(),
          );
            break;
        }
      },
      child: Text(goBack),
    );
  }
}

void navigatorAnimation(
    {required BuildContext context,
    required String goBack,
    required Widget destinationTo}) {
  Offset? begin;
  Navigator.of(context).push(
    PageRouteBuilder(
      pageBuilder: (context, animation, secondaryAnimation) {
        return destinationTo;
      },
      transitionDuration: const Duration(milliseconds: 300),
      transitionsBuilder: (context, animation, secondaryAnimation, child) {
        goBack == "send email" ? begin = const Offset(1.0, 0.0) : 0;
        const Offset end = Offset.zero;
        final Animatable<Offset> tween = Tween(begin: begin, end: end)
            .chain(CurveTween(curve: Curves.easeInOut));
        final Animation<Offset> offsetAnimation = animation.drive(tween);
        return SlideTransition(
          position: offsetAnimation,
          child: child,
        );
      },
    ),
  );
}


Solution

  • Try using FutureProvider

    final authProvider = FutureProvider<bool>(
      (ref) async => authUser(ref),
    );
    
    class Register3Widget extends ConsumerWidget {
      @override
      Widget build(BuildContext context, WidgetRef ref) {
    
        final authC = ref.watch(authProvider);
       
               ///
              authC.when(
                data: (data) => Text("Got Data "),
                error: (error, stackTrace) => Text("Got Error "),
                loading: () => CircularProgressIndicator(),
    
    
    }
    

    Changes on authUser

    Future<bool> authUser(ref) async {
      try {
        final FirebaseAuth auth = FirebaseAuth.instance;
        final UserCredential _result = await auth.createUserWithEmailAndPassword(
          email: "",
          password: "",
        );
        User _user = _result.user!;
        _user.sendEmailVerification();
        return true;
      } catch (e) {
        return false;
      }
    }
    

    or

    You may use initState and convert the widget to StatefulWidget, check the issue