I have a future builder which fetches an API

Everything works fine but I have an option to delete an item from the list. When I delete an item the list should get refreshed or the future function must be called.

My code

class ViewPlans extends StatefulWidget {
  static const id = 'ViewPlans';

  @override
  _ViewPlansState createState() => _ViewPlansState();
}

class _ViewPlansState extends State<ViewPlans> {
  PlannerService _plannerService = new PlannerService();

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Container(
          decoration: BoxDecoration(
              gradient: LinearGradient(
                  begin: Alignment.topLeft,
                  end: Alignment.bottomRight,
                  colors: [Color(gradStartColor), Color(gradEndColor)])),
          child: FutureBuilder(
            future: _plannerService.getPlans(),
            builder: (context, snapshot) {
              var plans = snapshot.data;
              if (plans == 'empty' || plans == null) {
                return Center(
                    child: CircularProgressIndicator(
                  valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
                ));
              }
              return RefreshIndicator(
                onRefresh: _plannerService.getPlans,
                child: ListView.separated(
                  physics: BouncingScrollPhysics(),
                  itemCount: plans.content.length,
                  padding: EdgeInsets.symmetric(horizontal: 30, vertical: 30),
                  separatorBuilder: (context, index) => null,
                  itemBuilder: (context, index) {
                    return Container(
                      height: 100,
                      child: Padding(
                        padding: const EdgeInsets.symmetric(vertical: 10),
                        child: Material(
                          elevation: 2,
                          shadowColor: Colors.white,
                          color: Colors.white,
                          borderRadius: BorderRadius.circular(10),
                          child: Center(
                            child: ListTile(
                              title: Text(
                                plans.content[index].task[0].toUpperCase() +
                                    plans.content[index].task.substring(1),
                                style: TextStyle(
                                    fontSize: 22,
                                    fontFamily: agne,
                                    color: Color(gradStartColor)),
                              ),
                              trailing: IconButton(
                                icon: Icon(
                                  Icons.delete,
                                  color: Color(gradStartColor),
                                ),
                                onPressed: () {
                                  _plannerService
                                      .deletePlan(plans.content[index].id)
                                      .then((value) => handleDelete(value));
                                },
                                splashRadius: 25,
                              ),
                            ),
                          ),
                        ),
                      ),
                    );
                  },
                ),
              );
            },
          ),
        ),
      ),
    );
  }

  handleDelete(value) {
    if (value == "deleted") {
      Fluttertoast.showToast(
          msg: 'Task deleted successfully',
          fontSize: 20,
          textColor: Colors.white,
          toastLength: Toast.LENGTH_SHORT,
          backgroundColor: Colors.black);
    } else {
      Fluttertoast.showToast(
          msg: 'Task deletion failed',
          fontSize: 20,
          textColor: Colors.white,
          toastLength: Toast.LENGTH_SHORT,
          backgroundColor: Colors.black);
    }
  }
}

In this code, I can't even see the refresh indicator.

give a solution please thanks in advance


Solution 1: towhid

A quick solution is to use the setState((){}) function after the completion of delete operation. This will recall the build function, and it will refresh your widget tree.


Solution 2: Omer Gamliel

You can create future variable and assign it to _plannerService.getPlans(). Use it in your future builder instead of _plannerService.getPlans(). Change onRefresh to setState((){future = _plannerService.getPlans()}). This code will rebuild your FutureBuilder with the updated data.

class ViewPlans extends StatefulWidget {
  static const id = 'ViewPlans';

  @override
  _ViewPlansState createState() => _ViewPlansState();
}

class _ViewPlansState extends State<ViewPlans> {
  PlannerService _plannerService = new PlannerService();
  Future<void> _future;

  @override
  void initState() {
  _future = _plannerService.getPlans();
  super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Container(
          decoration: BoxDecoration(
              gradient: LinearGradient(
                  begin: Alignment.topLeft,
                  end: Alignment.bottomRight,
                  colors: [Color(gradStartColor), Color(gradEndColor)])),
          child: FutureBuilder(
            future: _future,
            builder: (context, snapshot) {
              var plans = snapshot.data;
              if (plans == 'empty' || plans == null) {
                return Center(
                    child: CircularProgressIndicator(
                  valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
                ));
              }
              return RefreshIndicator(
                onRefresh: () {
                setState(() {
                _future = _plannerService.getPlans();
                })
                return Future.value(true);
                },
                child: ListView.separated(
                  physics: BouncingScrollPhysics(),
                  itemCount: plans.content.length,
                  padding: EdgeInsets.symmetric(horizontal: 30, vertical: 30),
                  separatorBuilder: (context, index) => null,
                  itemBuilder: (context, index) {
                    return Container(
                      height: 100,
                      child: Padding(
                        padding: const EdgeInsets.symmetric(vertical: 10),
                        child: Material(
                          elevation: 2,
                          shadowColor: Colors.white,
                          color: Colors.white,
                          borderRadius: BorderRadius.circular(10),
                          child: Center(
                            child: ListTile(
                              title: Text(
                                plans.content[index].task[0].toUpperCase() +
                                    plans.content[index].task.substring(1),
                                style: TextStyle(
                                    fontSize: 22,
                                    fontFamily: agne,
                                    color: Color(gradStartColor)),
                              ),
                              trailing: IconButton(
                                icon: Icon(
                                  Icons.delete,
                                  color: Color(gradStartColor),
                                ),
                                onPressed: () {
                                  _plannerService
                                      .deletePlan(plans.content[index].id)
                                      .then((value) => handleDelete(value));
                                },
                                splashRadius: 25,
                              ),
                            ),
                          ),
                        ),
                      ),
                    );
                  },
                ),
              );
            },
          ),
        ),
      ),
    );
  }