如何使用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)); }
关键修改说明
Isolate数据传递适配:
Isolate拥有独立内存空间,无法直接访问主线程的全局data,因此给Item添加序列化/反序列化方法,将数据转换成可跨Isolate传递的JSON格式。封装Isolate执行逻辑:
把父节点查找的完整逻辑(包括递归)封装成顶层函数findParentIdsInIsolate,作为compute的执行入口,确保逻辑在隔离线程中运行。异步任务管理:
用Future.wait等待所有compute任务完成,避免主线程提前执行后续逻辑导致数据未更新的问题。递归逻辑内部执行:
递归函数_findParentRecursive在Isolate内部调用,不会阻塞主线程,彻底解决卡顿问题。
内容的提问来源于stack exchange,提问作者Kel
相关产品推荐
相关产品推荐

