flutterdartfor-loopdio

how to update a variable in a function in every for loop?


 CharacterPage? currentPage;
   
...

 Future<dynamic> pageGetter(int i, CharacterPage? x) async {
    Dio dio = Dio();
    var pageData =
        await dio.get('https://rickandmortyapi.com/api/character?page=$i'); // => here i am 
    if (pageData.statusCode == HttpStatus.ok) {                             //updating the
      x = CharacterPage.fromJson(pageData.data);                            //page number
    }                                                                       //with int i
    if (mounted) {
      setState(() {});
    }
  }
 
...

 List<Character> filterByName() {
    pageGetter(1, currentPage);
  for (var v = 0; v < currentPage!.info.pages; v++) {
    pageGetter(v+1, currentPage);
  for (var i = 0; i < currentPage!.results.length; i++) {
    if (currentPage!.results.elementAt(i).name.contains("$nameFilterText")) {
      filteredByName.add(currentPage!.results.elementAt(i));
    }
  }
}

...

 TextButton(
                onPressed: () {
                  filteredByName = [];
                  results = filterByName();
                  setState(() {});
                },
                child: Text("Search"))

Here, what i am trying to do here is; on pressed, the Text button should run the pageGetter function which sends a get request. For example first it gets the page number 1, and makes a filtering on a parameter which is name, than adds objects to an empty list. Then i want it to get page number 2 with help of the for loop and make the same filtering on it untill there are no more pages left - there are 42 pages on this data here - which i am trying to do it on updating currentPage variable which is an instance of a class that i created. But everytime the inner for loop runs, it makes the filtering on the page number 1. i think the currentPage becomes updated when the all for loops concluded, which leads the same filtering on page 1 for 42 times. If i press that button again, i get random objects filtered from random pages.

I want this function to first make it's filtering on page 1, add the elements to the list than update the currentPage to page 2 than make the filtering on page 2 and add the elements and go on untill all the pages are filtered but i couldn't figure out why currentPage isn't updated during the process but at the end of it.

I hope I was clear about my problem, thanks in advance.


Solution

  • When you call pageGetter in a loop, it doesn't wait for the previous call to complete before making the next call.

    you can use async/await to wait for each call to pageGetter to complete before making the next call.

    List<Character> filterByName() async {
      currentPage = await pageGetter(1, currentPage);
      for (var v = 1; v <= currentPage!.info.pages; v++) {
        currentPage = await pageGetter(v, currentPage);
        for (var i = 0; i < currentPage!.results.length; i++) {
          if (currentPage!.results.elementAt(i).name.contains("$nameFilterText")) {
            filteredByName.add(currentPage!.results.elementAt(i));
          }
        }
      }
      return filteredByName;
    }
    

    Also, you'll need to modify your TextButton's onPressed callback to handle the asynchronous nature of the filterByName function:

    TextButton(
      onPressed: () async {
        filteredByName = [];
        results = await filterByName();
        setState(() {});
      },
      child: Text("Search"),
    )