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

Flutter桌面/Web执行复杂循环时应用卡顿问题求助

解决Flutter复杂逻辑阻塞UI的方案(结合Riverpod与Compute)

核心思路

把耗时的同步计算(如generateWithCombineClasses)从主线程移到独立的Isolate中执行,避免占用主线程导致UI冻结。Flutter的compute API封装了Isolate的创建与通信,使用起来更简便。

具体步骤

1. 调整耗时函数的结构

确保generateWithCombineClasses是顶层函数或类的静态方法,因为Isolate无法直接访问类的实例成员。如果需要传递多个参数,打包成可序列化的容器(如List或Map):

// 顶层函数示例
List<TimetableItem> generateWithCombineClasses(List<dynamic> params) {
  List<Course> courses = params[0];
  Map<String, dynamic> config = params[1];
  
  // 你的复杂循环、条件判断逻辑
  List<TimetableItem> result = [];
  // ... 执行计算逻辑
  return result;
}

注意:所有传入的参数(如Course类)必须支持Flutter的序列化,自定义类可通过json_serializable实现序列化能力。

2. 在Riverpod中集成Compute调用

根据你的状态管理方式,选择合适的Provider类型调用compute:

方式一:使用FutureProvider

适合一次性触发计算的场景:

final timetableProvider = FutureProvider<List<TimetableItem>>((ref) async {
  // 监听依赖的数据源
  final courses = ref.watch(coursesProvider);
  final config = ref.watch(timetableConfigProvider);
  
  // 调用compute执行耗时计算
  return compute(generateWithCombineClasses, [courses, config]);
});

方式二:使用StateNotifierProvider

适合需要主动触发计算的场景(比如用户点击按钮生成课程表):

class TimetableNotifier extends StateNotifier<AsyncValue<List<TimetableItem>>> {
  TimetableNotifier() : super(const AsyncLoading());

  Future<void> generateTimetable(List<Course> courses, Map<String, dynamic> config) async {
    state = const AsyncLoading();
    try {
      final result = await compute(generateWithCombineClasses, [courses, config]);
      state = AsyncData(result);
    } catch (e) {
      state = AsyncError(e, StackTrace.current);
    }
  }
}

final timetableNotifierProvider = StateNotifierProvider<TimetableNotifier, AsyncValue<List<TimetableItem>>>((ref) {
  return TimetableNotifier();
});

3. UI层响应状态变化

通过Consumer监听Provider状态,在计算过程中显示进度条,完成后展示结果:

Consumer(
  builder: (context, ref, child) {
    final timetableState = ref.watch(timetableProvider);
    return timetableState.when(
      loading: () => const CircularProgressIndicator(), // 进度条正常运行,不会卡顿
      error: (error, stack) => Text('生成失败:$error'),
      data: (timetable) => TimetableWidget(items: timetable),
    );
  },
)

关键注意事项

  • 不要在耗时函数中访问主线程资源(如UI组件、非线程安全的对象),Isolate拥有独立内存空间,无法共享这些资源。
  • Web端与Windows桌面端的Isolate实现差异已被Flutter的compute API封装,无需额外适配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 18:29:50