skip to Main Content

I am calling a function asynchronously to register user with phone number using Firebase. I want to show a CircularProgressIndicator while making the call as it takes little time to process the request. I used a state variable, isLoading, for this purpose. Whenever I call the async function, I set isLoading to true. In my widget tree, I have a if condition that shows a CircularProgressIndicator when this condition is true. But it is not showing the loader. Please help me understanding the control flow of this code.

Also, can I use Future builder here?

I have set isLoading = false initially.

if (isLoading)
              const Center(
                child: CircularProgressIndicator(),
              ),
            LoginButton(
              loginText: StaticText.sendCode,
              onTapButton: () async {
                setState(() {
                  isLoading = true;
                });

                // onClickSendCode calls another function asynchronously

                await AuthFunctions.onClickSendCode(
                  mobileController: mobileController,
                  context: context,
                );

                setState(() {
                  isLoading = false;
                });
              },
            ),
            if (isLoading)
              const Center(
                child: CircularProgressIndicator(),
              ),

This is my onClickSendCode function:

  // SENDING OTP
  static Future<void> onClickSendCode({
    required TextEditingController mobileController,
    required BuildContext context,
  }) async {
    if (mobileController.text.length != 10) {
      failureBar(StaticText.invalidPhoneNo, context);
      return;
    }
    FocusManager.instance.primaryFocus?.unfocus();

    print('circular');
    const CircularProgressIndicator();

    await AuthService().registerUserWithPhone(
      mobileController.text,
      context,
    );
  }

This is registerUserWithPhone:

  //  OTP
  Future<void> registerUserWithPhone(
    String mobile,
    BuildContext context,
  ) async {
    final auth = FirebaseAuth.instance;
    // print(mobile);
    await auth.verifyPhoneNumber(
      phoneNumber: '+91$mobile',
      verificationCompleted: (PhoneAuthCredential credential) {},
      verificationFailed: (FirebaseAuthException e) {},
      codeSent: (String verificationId, int? forceResendingToken) {
        Navigator.pushNamed(
          context,
          NamedRoutes.verifyCode,
          arguments: verificationId,
        );
      },
      codeAutoRetrievalTimeout: (String verificationId) {},
      timeout: const Duration(
        seconds: 120,
      ),
    );
  }
}

I tried to use Future builder but it also didn’t work. I couldn’t understand how setState method calls build method. Please help me.

2

Answers


  1. You can you use the valueListenable widget in this case in order to show the spinner or not by doing something like this.

    ValueListenableBuilder<bool>(
      valueListenable: isLoading,
      child: child, //Widgets that are always shown
      builder: (context, isLoading, child) {
       //The widgets you want to display when isLoading == true
      })
    );
    

    I would go this route in your case.

    Additionally you can implement BLOC to handle the states of your widgets. This is a bit more complex way to handle this scenario but it’s more robust in the end.

    Login or Signup to reply.
  2. I don’t know the reason or explanation behind this but this usually works for me instead:

    isLoading 
      ? const Center(child: CircularProgressIndicator())
      : LoginButton(...);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search