harunB10
harunB10

Reputation: 5207

Flutter FutureBuilder show Progress indicator

I have a button which onpressed inserts something in DB and redirects user to another page. I am trying to implement FutureBuilder which should show CircularProgressIndicator until everything is done.

This is my function:

Future<bool> insertPhoneNumber(String phoneNumber) async {
    String token = await getToken();

    if (token.isNotEmpty) {
      var body = jsonEncode({'token': token, 'userID': user.getUserID(), 'phoneNumber': phoneNumber});

      print(body.toString());

      var res = await http.post((baseUrl + "/insertPhoneNumber/" + user.getUserID()),
          body: body,
          headers: {
            "Accept": "application/json",
            "content-type": "application/json"
          });

      if (res.statusCode == 200) {
        print("Insert Phone Number is OK");
        notifyListeners();
        return true;
      } else {
        print("Insert Phone Number not OK");
        notifyListeners();
        return false;
      }
    } else {
      print("Insert Phone Number failed due to unexisting token");
    }
  }

and this is a button which triggers DB interaction:

RaisedButton(
                  color: Color.fromRGBO(105, 79, 150, 1),
                  onPressed: () {
                    var user = Provider.of<UserRepository>(context);
                    String completePhoneNumber = _selectedDialogCountry.phoneCode + phoneNumberController.text;
                    FutureBuilder(
                      future: user.insertPhoneNumber(completePhoneNumber),
                      builder: (BuildContext context, AsyncSnapshot snapshot) {
                        if (snapshot.connectionState != ConnectionState.done) {
                          return CircularProgressIndicator(
                              backgroundColor: Colors.blue);
                        } else {
                          return Dashboard();
                        }
                      },
                    );
                  },
                  textColor: Colors.white,
                  child: Text("SAVE"),
                )

It updates DB but nothing else happens. There is no progress indicator nor redirection to Dashboard.

EDIT

This is my full build method:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
          padding: EdgeInsets.all(8.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              AutoSizeText(
                'What is your phone number?',
                style: TextStyle(fontSize: 30),
                maxLines: 1,
              ),
              Row(
                children: <Widget>[
                  SizedBox(
                    width: 9.0,
                    child: Icon(Icons.arrow_downward),
                  ),
                  SizedBox(width: 8.0),
                  SizedBox(
                      width: 120.0,
                      height: 65.0,
                      child: Card(
                        child: ListTile(
                          onTap: _openCountryPickerDialog,
                          title: _buildDialogItem(_selectedDialogCountry),
                        ),
                      )),
                  Expanded(
                    child: TextField(
                        autofocus: true,
                        keyboardType: TextInputType.number,
                        decoration:
                            InputDecoration(border: OutlineInputBorder())),
                  ),
                ],
              ),
              SizedBox(
                width: 100,
                child: RaisedButton(
                  color: Color.fromRGBO(105, 79, 150, 1),
                  onPressed: () {
                    print("Test");
                  },
                  textColor: Colors.white,
                  child: Text("SAVE"),
                ),
              )
            ],
          )),
    );
  }

Upvotes: 5

Views: 8830

Answers (1)

Farmaan Elahi
Farmaan Elahi

Reputation: 1650

It is not working because the FutureBuilder isn't attached to the Widget tree. The once the future is not in done state, it is just creating an instance Dashboard.You shouldn't be using FutureBuilder here instead you can set the child widget based on some variable and when future complete, you call setState on the that variable to update the state which will in-turn rebuild the widget with the new state value

Something like this

var isLoading = false;

void insertNumber(){
 var user = Provider.of<UserRepository>(context);
 String completePhoneNumber = _selectedDialogCountry.phoneCode + phoneNumberController.text;
 setState(() => isLoading=true);
 user.insertPhoneNumber(completePhoneNumber).then((result){
  setState(() => isLoading=false);
 })
}

Widget build(BuildContext context){
 return RaisedButton(
                  color: Color.fromRGBO(105, 79, 150, 1),
                  onPressed: () {
                    var user = Provider.of<UserRepository>(context);
                    String completePhoneNumber = _selectedDialogCountry.phoneCode + phoneNumberController.text;
                    FutureBuilder(
                      future: user.insertPhoneNumber(completePhoneNumber),
                      builder: (BuildContext context, AsyncSnapshot snapshot) {
                        if (snapshot.connectionState != ConnectionState.done) {
                          return CircularProgressIndicator(
                              backgroundColor: Colors.blue);
                        } else {
                          return Dashboard();
                        }
                      },
                    );
                  },
                  textColor: Colors.white,
                  child: isLoading? CircularProgressIndicator(): Text("Save"),
                );
}

For your use case, you will need more that two state to achieve the UI you are looking for .Example DEFAULT,LOADING,ERROR,SUCCESS

Upvotes: 6

Related Questions