【问题标题】:Dart- Isolates are very slow when working with listsDart - 使用列表时隔离非常慢
【发布时间】:2022-01-17 10:32:45
【问题描述】:

我想从一个字符串生成一个包含 300 个项目的列表,但是当这个任务被分成 3 个隔离时,每个隔离生成一个包含 100 个项目的列表,它需要的时间与单个隔离生成一个300 项的列表。

下面的 fetchCoinList() 方法是在隔离中运行的,generateList() 方法产生 3 个隔离。

所有这些隔离确实并行工作并返回各自的列表。

List<CoinData> fetchCoinList(ListConfig listConfig) {
  List<CoinData> coinList = [];

  for (int index = listConfig.listStart; index < listConfig.listEnd; index++) {
    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';
    print(listConfig.listEnd);

    coinList.add(CoinData(rank, id, name, symbol, value, percentChange, image));
  }
  return coinList;
}

Future<List<CoinData>> generateList(String response) async {
  print("Inside isolate");

  List<CoinData> coinList = [];
  List list = [];

  for (int i = 0; i < 3; i++) {
    ListConfig listConfig = ListConfig(response, i * 100, (i * 100) + 100);
    list.add(compute(fetchCoinList, listConfig));
  }

  for (int i = 0; i < 3; i++) {
    coinList = coinList + await list[i];
  }

  return coinList;
}

有什么办法可以解决这个问题?如果需要(不挂主线程),如何生成 300 或 1000 个项目的列表?

【问题讨论】:

  • 请不要针对同一主题创建多个问题。你已经发布了:stackoverflow.com/questions/70730674/…
  • “如果需要(不挂主线程),如何生成一个包含 300 或 1000 个项目的列表?” - 所以现在你打电话给compute运行三遍,主线程挂了?
  • 话虽如此。在您的示例中不清楚您如何从主隔离中调用这些方法。
  • @pskink 在这种情况下,主线程不会挂起,但是隔离生成它们各自的列表需要很长时间......如果我要在主线程上生成一个包含 300 个项目的列表会在更短的时间内生成它,但它会导致用户界面在这段时间内冻结。
  • 还应该注意fetchCoinList 根本没有以任何有效的方式编写。每次需要数据结构中的元素而不是保存jsonDecode 的结果时,您都调用jsonDecode,这实际上有点可怕。

标签: multithreading flutter dart dart-isolates


【解决方案1】:

您的主要问题可能是您在 fetchCoinList 中处理 JSON 解析的方式有点糟糕,您在其中为要从 JSON 字符串中提取的每个字段运行 jsonDecode()

您应该缓存来自jsonDecode() 的结果。此外,您还应该缓存一些您经常执行的其他操作。

我做了以下示例来说明我将如何重写代码:

List<CoinData> fetchCoinList(ListConfig listConfig) {
  final jsonObject = jsonDecode(listConfig.listData) as Map<String, dynamic>;
  List<CoinData> coinList = [];

  for (int index = listConfig.listStart; index < listConfig.listEnd; index++) {
    final dataMap = jsonObject['data'][index] as Map<String, dynamic>;

    if (dataMap['rank'] == null ||
        dataMap['priceUsd'] == null ||
        dataMap['changePercent24Hr'] == null) continue;

    print(listConfig.listEnd);

    final symbol = dataMap['symbol'] as String;

    coinList.add(CoinData(
        rank: dataMap['rank'] as int,
        name: dataMap['name'] as String,
        symbol: symbol,
        id: dataMap['id'] as String,
        value: double.parse(jsonObject['priceUsd'] as String),
        percentChange: double.parse(jsonObject['changePercent24Hr'] as String),
        image:
            'https://static.coincap.io/assets/icons/${symbol.toLowerCase()}@2x.png'));
  }
  return coinList;
}

class CoinData {
  final int rank;
  final String name;
  final String symbol;
  final String id;
  final double value;
  final double percentChange;
  final String image;

  CoinData({
    required this.rank,
    required this.name,
    required this.symbol,
    required this.id,
    required this.value,
    required this.percentChange,
    required this.image,
  });
}

【讨论】:

  • 实施此解决方案确实显着提高了性能,因此我只需要使用一个单独的隔离...谢谢。
猜你喜欢
  • 2021-10-16
  • 1970-01-01
  • 1970-01-01
  • 2012-05-28
  • 1970-01-01
  • 2017-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多