You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用compute函数为recursive function创建Isolate解决Flutter应用卡顿

解决递归函数卡顿问题:通过Compute创建Isolate优化

问题背景

处理大规模数据时,递归函数导致应用卡顿数秒,需要借助compute函数将递归逻辑移到隔离线程(Isolate)中执行,避免阻塞主线程。

修改后的完整代码

import 'package:flutter/foundation.dart';

class Item {
  Item({this.id, this.childIds, this.parentIds});

  final String id;
  final List<String>? childIds;
  List<String>? parentIds;

  // 序列化方法,用于Isolate间数据传递
  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'childIds': childIds,
      'parentIds': parentIds,
    };
  }

  // 反序列化方法,从Isolate返回的数据重建对象
  factory Item.fromJson(Map<String, dynamic> json) {
    return Item(
      id: json['id'],
      childIds: json['childIds'] != null ? List<String>.from(json['childIds']) : null,
      parentIds: json['parentIds'] != null ? List<String>.from(json['parentIds']) : null,
    );
  }

  @override
  String toString() {
    return 'Item{id: $id, childIds: $childIds, parentIds: $parentIds}';
  }
}

List<Item> data = [
  Item(id: 'aaa', childIds: ['ccc']),
  Item(id: 'bbb', childIds: ['ccc', 'ddd']),
  Item(id: 'ccc', childIds: ['ggg']),
  Item(id: 'ddd', childIds: ['fff', 'hhh']),
  Item(id: 'eee', childIds: ['hhh']),
  Item(id: 'fff', childIds: ['ggg']),
  Item(id: 'ggg', childIds: null),
  Item(id: 'hhh', childIds: null),
];

// 顶层函数:在Isolate中执行父节点查找逻辑
List<String> findParentIdsInIsolate(Map<String, dynamic> args) {
  final String targetId = args['id'];
  final List<Item> data = (args['data'] as List).map((json) => Item.fromJson(json)).toList();
  
  return _idFindParent(targetId, data);
}

List<String> _idFindParent(String id, List<Item> data) {
  final List<Item> itemsHasChild = data.where((e) => e.childIds != null).toList();
  final List<Item> parents = itemsHasChild.where((parent) => parent.childIds!.contains(id)).toList();
  
  if (parents.isEmpty) return [];
  
  final List<String> parentIds = parents.map((e) => e.id).toSet().toList();
  return _findParentRecursive(parentIds, data);
}

List<String> _findParentRecursive(List<String> ids, List<Item> data) {
  final bool everyParentIsEmpty = ids.every((id) {
    final List<Item> itemsHasChild = data.where((e) => e.childIds != null).toList();
    return itemsHasChild.where((e) => e.childIds!.contains(id)).isEmpty;
  });

  if (everyParentIsEmpty) return ids;

  final List<String> _ids = [];
  for (final String id in ids) {
    final List<Item> itemsHasChild = data.where((e) => e.childIds != null).toList();
    final List<Item> parents = itemsHasChild.where((e) => e.childIds!.contains(id)).toList();
    
    if (parents.isEmpty) {
      _ids.add(id);
    } else {
      _ids.addAll(parents.map((e) => e.id));
    }
  }

  return _findParentRecursive(_ids.toSet().toList(), data);
}

void main() async {
  // 将数据序列化,以便传递到Isolate
  final List<Map<String, dynamic>> serializedData = data.map((item) => item.toJson()).toList();

  // 为每个Item启动Isolate执行父节点查找
  final List<Future<void>> futures = data.map((e) async {
    e.parentIds = await compute(
      findParentIdsInIsolate,
      {'id': e.id, 'data': serializedData},
    );
  }).toList();

  // 等待所有Isolate任务完成
  await Future.wait(futures);

  // 输出结果
  data.forEach((e) => print(e));
}

关键修改说明

  1. Isolate数据传递适配:
    Isolate拥有独立内存空间,无法直接访问主线程的全局data,因此给Item添加序列化/反序列化方法,将数据转换成可跨Isolate传递的JSON格式。

  2. 封装Isolate执行逻辑:
    把父节点查找的完整逻辑(包括递归)封装成顶层函数findParentIdsInIsolate,作为compute的执行入口,确保逻辑在隔离线程中运行。

  3. 异步任务管理:
    用Future.wait等待所有compute任务完成,避免主线程提前执行后续逻辑导致数据未更新的问题。

  4. 递归逻辑内部执行:
    递归函数_findParentRecursive在Isolate内部调用,不会阻塞主线程,彻底解决卡顿问题。

内容的提问来源于stack exchange,提问作者Kel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 12:30:42