4

I am generating a list of a thousand items from an api response, this would hang my main thread so I seperated this task to five seperate isolates using the compute() method, where each isolate generates a part of the list,each containing 200 items. I create all these isolates using a sixth isolate which combines all the lists and returns them to the main thread where it's being loaded.

Everything works fine except that the main thread still hangs for a bit, the refresh indicator on my list-view still hangs for the first 15 seconds or so...


    List<CoinData> fetchCoinList(ListConfig listConfig){
      List<CoinData> coinList = [];
    
      for(int index = listConfig.listStart; index < listConfig.listEnd; index++){
        print("In Isolate with range ${listConfig.listStart} - ${listConfig.listEnd} ");
        if(jsonDecode(listConfig.listData)['data'][index]['rank'] == null||
            jsonDecode(listConfig.listData)['data'][index]['priceUsd'] == null ||
            jsonDecode(listConfig.listData)['data'][index]['changePercent24Hr'] ==null)
          continue;
    
        int rank = int.parse(jsonDecode(listConfig.listData)['data'][index]['rank']);
        String name = jsonDecode(listConfig.listData)['data'][index]['name'];
        String symbol = jsonDecode(listConfig.listData)['data'][index]['symbol'];
        String id = jsonDecode(listConfig.listData)['data'][index]['id']??"";
        double value =
        double.parse(jsonDecode(listConfig.listData)['data'][index]['priceUsd']);
        double percentChange = double.parse(
            jsonDecode(listConfig.listData)['data'][index]['changePercent24Hr']);
        String image =
            'https://static.coincap.io/assets/icons/${symbol
            .toLowerCase()}@2x.png';
    
    
        coinList.add(CoinData(rank, id, name, symbol, value, percentChange, image));
    
      }
      return coinList;
    }
    Future <List<CoinData>> generateList(String response) async {
      List<CoinData> coinList;
      print("Inside isolate");
      ListConfig listConfig1 = ListConfig(response, 0, 200);
    
      ListConfig listConfig2 = ListConfig(response, 200, 400);
    
      ListConfig listConfig3 = ListConfig(response, 400, 600);
    
      ListConfig listConfig4 = ListConfig(response, 600, 800);
    
      ListConfig listConfig5 = ListConfig(response, 800, 1000);
    
//creating 5 isolates and waiting for their execution
    
      var results =  await Future.wait([
        compute(fetchCoinList,listConfig1),compute(fetchCoinList,listConfig2),compute(fetchCoinList,listConfig3),compute(fetchCoinList,listConfig4),compute(fetchCoinList,listConfig5)
    
      ]);
    
      coinList = results[0] + results[1] + results[2] +results[3] + results[4];
    
    
    
      return coinList;
    
    }

The isolate is being called in the main thread using this function...

 Future<void> fetchData() async {
    setState(() {
      loading = true;//unrelated to the refreshindicator widget
    });

    for (int i = 0; i < 3; i++) {
      await widget.mynetwork.startNetwork();
      if (widget.mynetwork.cryptoData.isNotEmpty) break;
      print('Restarting Network...');
    }

   if(widget.mynetwork.cryptoData.isNotEmpty){
     print("creating list");

     widget.cryptoList =  await compute(generateList,widget.mynetwork.cryptoData);

   }
    setState(() {
      loading = false;
    });
  }

widget where the function is being triggered

RefreshIndicator(
                    onRefresh: fetchData,
                    child: ListView.separated(
                      physics: BouncingScrollPhysics(),
                      scrollDirection: Axis.vertical,
                      itemBuilder: (context, index) {
                        return filteredList.isNotEmpty ? CoinTile(
                            filteredList[index]
                        ):CoinTile(
                            widget.cryptoList[index]
                        );
                      },
                      itemCount: filteredList.isEmpty ? widget.cryptoList.length : filteredList.length,
                      separatorBuilder: (context, index) {
                        return Divider(
                          height: 1,
                          thickness: 1,
                          color: Colors.grey.shade100,
                        );
                      },
                    ),
                  ),
Hamza Baig
  • 53
  • 6
  • 2
    What version of Flutter and Dart are you using in your project? There have been some recent performance improvements for `compute` with Dart 2.15 (combined with latest version of Flutter) which should make it much cheaper to send big objects from one isolate to another if the sending is happening as part of the sending isolate being stopped. – julemand101 Jan 16 '22 at 13:59
  • I guess it would be more clear if you add the full code of where you call the isolate in main thread. – Sergio Jan 16 '22 at 14:05
  • I'm using the latest stable versions of dart and flutter. So sending objects from one isolate to others which in my case are 5 is whats causing my main thread to hang? I would've thought that seperating this task to another isolate would avoid this issue. – Hamza Baig Jan 16 '22 at 14:11
  • @HamzaBaig Well, it really depends on what is exactly going on in your application. It is just a common observation that people thinks it is "free" to move data between isolates. But as I said, there have been some recent optimizations going to to make it much cheaper to "send" data from one isolate to another in case the isolate are going to be stopped (e.g. if it returns on value) since we don't need to copy the object but can just point to it (since we know for a fact that there are still only one isolate using the object afterwards). – julemand101 Jan 16 '22 at 14:14
  • You can read the following article to understand how isolates, and communications with them, works: https://dart.dev/guides/language/concurrency – julemand101 Jan 16 '22 at 14:16
  • I did observe that when the whole list of 1000 items is generated in just a single isolate outside the main thread, the ui doesn't freeze at all. Also another observation was that the ui unfreezes when only last two threads of the 5 are executing and the remaining have completed execution. Anyways thanks for your input, I appreciate it. – Hamza Baig Jan 16 '22 at 14:53
  • Closed the question since it was posted twice and the actual solution was found in the second issue (spoiler: badly way to do JSON parsing). – julemand101 Jan 17 '22 at 12:19

0 Answers0