skip to Main Content

I have the below code for fetching updated data on changing the filter value and pressing update. The data is getting fetched, but the list is not getting updated. How to make this work. The list is showing properly once loaded but it is not updating.

child: ElevatedButton(
  style: ElevatedButton.styleFrom(
    primary: Colors.red,
  ),
  onPressed: () async {
    setState(() {
      accordianFlag = false;
    });
    // programsListFuture = getCropNutritionPrograms();
    // var updatedProgramsList = await getCropNutritionPrograms();
    // setState(() {
    //   programsListFuture = Future.value(updatedProgramsList);
    // });
    fetchData();  // <--- not working. I tried various other method, but list is not updating
  },
  child: Text(
    'Update',
    style: TextStyle(
      color: Colors.white,
      fontWeight: FontWeight.bold
    ),
  ),
)

Full code:

class CropNutritionProgramOverviewScreen extends StatefulWidget {
  CropNutritionProgramOverviewScreen({Key? key, required this.showAppbar, required this.showBottombar}) : super(key: key);
  bool showAppbar = false;
  bool showBottombar = false;

  @override
  State<CropNutritionProgramOverviewScreen> createState() => _CropNutritionProgramOverviewScreenState();
}

class _CropNutritionProgramOverviewScreenState extends State<CropNutritionProgramOverviewScreen> {
  Future<RegionsList?>? regionsListFuture;
  Future<CropsModel?>? cropsListFuture;
  Future<CropNutritionProgramModel?>? programsListFuture;
  bool accordianFlag = false;
  bool _showContent = false;
  String regionSelected = '1';
  String cropSelected = '0';
  List<DropdownMenuItem<String>> regionDropdownItems = [];
  List<DropdownMenuItem<String>> cropDropdownItems = [];

  _CropNutritionProgramOverviewScreenState();

  @override
  void initState() {
    super.initState();
  }

  Future<RegionsList?> getRegions() async {
    RegionsList regionsList = await getRegionsAPI();
    print("flutter - regions list: " + regionsList.toString());
    
    List<Region> regions = regionsList.regions ?? [];
    for (Region region in regions) {
      regionDropdownItems.add(DropdownMenuItem(
        child: Text(region.name),
        value: region.id.toString(),
      ));
    }
    if (regions.length > 0) {
      regionSelected = regions[0].id.toString();
    }

    return regionsList;
  }

  Future<CropsModel?> getCrops(int regionId) async {
    CropsModel cropsList = await getCropsAPI(regionId);
    print("flutter - cropsList: " + cropsList.toString());

    List<Crop> crops = cropsList.cropsList ?? [];
    for (Crop crop in crops) {
      cropDropdownItems.add(DropdownMenuItem(
        child: Text(crop.name),
        value: crop.id.toString(),
      ));
    }

    return cropsList;
  }

  Future<CropNutritionProgramModel?> getCropNutritionPrograms() async {
    var regionId = int.parse(regionSelected);
    var cropId = int.parse(cropSelected);
    CropNutritionProgramModel programsModel = await getCropNutritionProgramsAPI(regionId, cropId);
    print("flutter - cropNutritionProgramsModel: " + programsModel.toString());
    return programsModel;
  }

  Future<List<dynamic>> fetchData() async {
    return await Future.wait([getRegions(), getCrops(0), getCropNutritionPrograms()]);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: widget.showAppbar ? TopAppBar() : null,
      drawer: widget.showAppbar ? TopDrawer() : null,
      body: FutureBuilder<List<dynamic>>(
        future: fetchData(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return _buildLoadingIndicator();
          } else if (snapshot.hasError) {
            return Text('Error: ${snapshot.error}');
          } else if (snapshot.hasData) {
            var regionsList = snapshot.data?.elementAt(0) as RegionsList?;
            var cropsList = snapshot.data?.elementAt(1) as CropsModel?;
            var programsList = snapshot.data?.elementAt(2) as CropNutritionProgramModel?;
            List<Region> regions = regionsList == null ? [] : regionsList!.regions;
            List<Crop> crops = cropsList == null ? [] : cropsList!.cropsList;
            List<CropNutritionProgram> programs = programsList == null ? [] : programsList.cropNutritionPrograms;
            return Container(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Padding(
                    padding: const EdgeInsets.only(top: 16, left: 16, bottom: 8),
                    child: Text(
                      'Crop Nutrition Programs',
                      style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
                    ),
                  ),
                  Expanded(
                    child: SingleChildScrollView(
                      child: Container(
                        padding: EdgeInsets.fromLTRB(8.0, 0.0, 8.0, 8.0),
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            SizedBox(height: 4.0),
                            Image.asset(
                              regionsAssetPath,
                              fit: BoxFit.cover,
                            ),
                            SizedBox(height: 16.0),
                            Center(
                              child: Text(
                                "Discover Crop Nutrition Program recommendations for your state!",
                                textAlign: TextAlign.center,
                              ),
                            ),
                            SizedBox(height: 16.0),
                            Padding(
                              padding: const EdgeInsets.only(left: 16.0, right: 16.0, top: 0.0, bottom: 8.0),
                              child: StatefulBuilder(
                                builder: (BuildContext context, StateSetter setState) {
                                  return Card(
                                    shape: new RoundedRectangleBorder(
                                      side: new BorderSide(color: Colors.red, width: 1.0),
                                      borderRadius: BorderRadius.circular(4.0),
                                    ),
                                    child: Column(
                                      children: [
                                        Container(
                                          height: 40,
                                          child: Transform.translate(
                                            offset: Offset(0, -8),
                                            child: ListTile(
                                              title: const Text("Filter By", style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16, color: Colors.red)),
                                              leading: Icon(Icons.filter_alt_outlined, color: Colors.red,),
                                              trailing: IconButton(
                                                icon: Icon(
                                                  _showContent ? Icons.arrow_drop_up : Icons.arrow_drop_down, color: Colors.red,),
                                                onPressed: () {
                                                  setState(() {
                                                    _showContent = !_showContent;
                                                  });
                                                },
                                              ),
                                              onTap: () {
                                                setState(() {
                                                  _showContent = !_showContent;
                                                });
                                              },
                                            ),
                                          ),
                                          decoration: new BoxDecoration(
                                            border: new Border(bottom: new BorderSide(color: Colors.red)),
                                          ),
                                        ),
                                        _showContent
                                        ? Container(
                                            padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5),
                                            child: Column(
                                              crossAxisAlignment: CrossAxisAlignment.start,
                                              mainAxisSize: MainAxisSize.min,
                                              children: [
                                                SizedBox(
                                                  height: 5,
                                                ),
                                                Padding(
                                                  padding:
                                                  const EdgeInsets.only(left: GlobalMargin.leftAccordian, right: GlobalMargin.rightAccordian),
                                                  child: InputDecorator(
                                                    decoration: const InputDecoration(
                                                        contentPadding: EdgeInsets.symmetric(horizontal: 8, vertical: 0),
                                                        border: OutlineInputBorder(),
                                                    ),
                                                    child: DropdownButtonHideUnderline(
                                                      child: DropdownButton<String>(
                                                        value: regionSelected,
                                                        isExpanded: true,
                                                        isDense: true,
                                                        hint: Text('Select Region'),
                                                        icon:
                                                        const Icon(Icons.arrow_drop_down_outlined),
                                                        style: const TextStyle(color: Colors.black),
                                                        onChanged: (value) {
                                                          setState(() {
                                                            accordianFlag = true;
                                                            if (value != null) {
                                                              regionSelected = value;
                                                            }
                                                          });
                                                        },
                                                        items: regionDropdownItems
                                                      ),
                                                    ),
                                                  ),
                                                ),
                                                SizedBox(
                                                  height: 10,
                                                ),
                                                Padding(
                                                  padding:
                                                  const EdgeInsets.only(left: GlobalMargin.leftAccordian, right: GlobalMargin.rightAccordian),
                                                  child: InputDecorator(
                                                    decoration: const InputDecoration(
                                                        contentPadding: EdgeInsets.symmetric(horizontal: 8, vertical: 0),
                                                        border: OutlineInputBorder(),
                                                    ),
                                                    child: DropdownButtonHideUnderline(
                                                      child: DropdownButton<String>(
                                                        value: cropSelected,
                                                        isExpanded: true,
                                                        isDense: true,
                                                        hint: Text('Select Crop'),
                                                        icon:
                                                        const Icon(Icons.arrow_drop_down_outlined),
                                                        style: const TextStyle(color: Colors.black),
                                                        onChanged: (value) {
                                                          setState(() {
                                                            accordianFlag = true;
                                                            if (value != null) {
                                                              cropSelected = value;
                                                            }
                                                          });
                                                        },
                                                        items: cropDropdownItems,
                                                      ),
                                                    ),
                                                  ),
                                                ),
                                                SizedBox(
                                                  height: 10,
                                                ),
                                                Container(
                                                  width: double.infinity,
                                                  alignment: Alignment.topCenter,
                                                  child: Container(
                                                    width: 200,
                                                    child: ElevatedButton(
                                                      style: ElevatedButton.styleFrom(
                                                        primary: Colors.red,
                                                      ),
                                                      onPressed: () async {
                                                        setState(() {
                                                          accordianFlag = false;
                                                        });
                                                        // programsListFuture = getCropNutritionPrograms();
                                                        // var updatedProgramsList = await getCropNutritionPrograms();
                                                        // setState(() {
                                                        //   programsListFuture = Future.value(updatedProgramsList);
                                                        // });
                                                        fetchData();
                                                      },
                                                      child: Text(
                                                        'Update',
                                                        style: TextStyle(
                                                          color: Colors.white,
                                                          fontWeight: FontWeight.bold
                                                        ),
                                                      ),
                                                    )
                                                  )
                                                ),
                                              ],
                                            ),
                                          )
                                        : Container(),
                                      ],
                                    ),
                                  );
                                },
                              ),
                            ),
                            ListView.separated(
                              shrinkWrap: true,
                              physics: NeverScrollableScrollPhysics(),
                              itemCount: programs.length,
                              separatorBuilder: (_, __) => Divider(height: 1),
                              itemBuilder: (context, index) {
                                return Padding(
                                  padding: EdgeInsets.fromLTRB(-8, 8, 0, 8),
                                  child: ListTile(
                                    title: Text("${programs[index].name}"),
                                    trailing: Icon(Icons.arrow_forward, color: Colors.red),
                                    onTap: () {
                                      print("crop nutrition program tapped");
                                      navigateToCropNutritionListScreen(context, int.parse(regionSelected), 0);
                                    },
                                  ),
                                );
                              }
                            ),
                          ]
                        ),
                      ),
                    ),
                  ),  
                ],
              ),
            );
          } else {
            return Text('No data available');
          }
        },
      ),
    );
  }

  void navigateToCropNutritionListScreen(BuildContext context, int regionId, int stateId) {
    var provider = Provider.of<AppBarContitonProvider>(
      context,
      listen: false,
    );
    provider.setInnerPageLoaded(true);
    provider.setPdfScreenLoaded(false, '');
    NavKey.key.currentState?.pushNamed(Routes.cropNutritionList, 
      arguments: CropNutritionListArguments(regionId, stateId)).then((value) {
    });
  }

  Widget _buildLoadingIndicator() {
    return Padding(
      padding: EdgeInsets.all(8.0),
      child: Center(
        child: CircularProgressIndicator(),
      ),
    );
  }
}


I have updated the code to use only one future variable but still the list is not rebuilding when new data is fetched.
Code: https://pastebin.com/AYENDAkr

Could you please help me with this? Thanks.


I am new to flutter. I don’t understand why when a variable changes the corresponding widget does not update.

programsListFuture = getCropNutritionPrograms();
var updatedProgramsList = await getCropNutritionPrograms();
  setState(() {
    programsListFuture = Future.value(updatedProgramsList);
});

The future is assigned new value, but why is the list not updated?

2

Answers


  1. try and reorganize the way you initialize the app, using the future builder like this and creating the future in itself is an error, start by working this out before moving to your described bug, see the flutter youtube channel on this take https://www.youtube.com/watch?v=zEdw_1B7JHY

     //Dont to 
     FutureBuilder<List<dynamic>>(
     future: fetchData(),
    
    Login or Signup to reply.
  2. If you want to continuously monitor the changes of a certain attribute, you can use ValueListenableBuilder and ValueNotifier to achieve that.

    ValueListenableBuilder DartPad

    You can run this DartPad to see the effect.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search