Flutter进阶:高内存任务的动态并发执行完美实现

一、需求来源

flutter 项目中会遇到多文件上传或者下载之类的批量执行任务就需要控制并发数量(避免内存爆炸或者数据传输效率过差),今天灵光一闪,实现一个极简的,分享给大家。

内存爆炸: 一般表现为app闪退。

数据传输效率过差:一般表现为并发数量较多时,每个任务的速度都很慢,减少并发数可以显著提升速度(上传下载同理)。

二、使用示例

复制代码
假设任务总数是 10,最大并发是 3,每个任务耗时 1 秒完成,执行过程如下:

》执行任务0
》执行任务1
》执行任务2
》任务0 完成,3开始
》任务1 完成,4开始
》任务2 完成,5开始
》任务3 完成,6开始
》任务4 完成,7开始
》任务5 完成,8开始
》任务6 完成,9开始
》任务7 完成
》任务8 完成
》任务9 完成

三、源码

dart 复制代码
import 'dart:collection';

import 'package:flutter/material.dart';
import 'package:flutter_templet_project/extension/dlog.dart';
import 'package:get/get.dart';

class ConcurrentExecutorDemo extends StatefulWidget {
  const ConcurrentExecutorDemo({
    super.key,
    this.arguments,
  });

  final Map<String, dynamic>? arguments;

  @override
  State<ConcurrentExecutorDemo> createState() => _ConcurrentExecutorDemoState();
}

class _ConcurrentExecutorDemoState extends State<ConcurrentExecutorDemo> {
  final scrollController = ScrollController();

  Map<String, dynamic> arguments = Get.arguments ?? <String, dynamic>{};

  /// 任务数
  var taskCount = 10;

  /// 并发数量
  var maxConcurrent = 3;

  /// 执行描述
  final descVN = ValueNotifier("");

  String get timeStr => DateTime.now().toString();

  @override
  void didUpdateWidget(covariant ConcurrentExecutorDemo oldWidget) {
    super.didUpdateWidget(oldWidget);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("$widget"),
      ),
      body: buildBody(),
    );
  }

  Widget buildBody() {
    return Scrollbar(
      controller: scrollController,
      child: SingleChildScrollView(
        controller: scrollController,
        child: Column(
          children: [
            Text("并发执行(总数:$taskCount, 最大并发数: $maxConcurrent):"),
            ElevatedButton(onPressed: onTest, child: Text("开始执行")),
            ValueListenableBuilder(
              valueListenable: descVN,
              builder: (context, value, child) {
                return Text(value);
              },
            ),
          ],
        ),
      ),
    );
  }

  Future<void> onTest() async {
    descVN.value = "";

    final executor = ConcurrentExecutor(maxConcurrent: maxConcurrent);

    for (var i = 0; i < taskCount; i++) {
      final id = i;
      executor.add(() async {
        DLog.d('Start $id');
        descVN.value += "[$timeStr]Start $id\n";
        await Future.delayed(Duration(seconds: 1));
        DLog.d('Done $id');
        descVN.value += "[$timeStr]Done $id\n";
      });
    }

    await executor.waitForEmpty();
    DLog.d('All tasks complete');
    descVN.value += "[$timeStr]All tasks complete";
  }
}

/// 并发执行器
class ConcurrentExecutor {
  ConcurrentExecutor({this.maxConcurrent = 3});

  final int maxConcurrent;
  final Queue<Future<void> Function()> _taskQueue = Queue();
  int _running = 0;

  void add(Future<void> Function() task) {
    _taskQueue.add(task);
    _tryExecuteNext();
  }

  void _tryExecuteNext() {
    while (_running < maxConcurrent && _taskQueue.isNotEmpty) {
      final task = _taskQueue.removeFirst();
      _running++;
      task().whenComplete(() {
        _running--;
        _tryExecuteNext();
      });
    }
  }

  Future<void> waitForEmpty() async {
    while (_taskQueue.isNotEmpty || _running > 0) {
      await Future.delayed(Duration(milliseconds: 50));
    }
  }
}

最后、总结

1、本质上任务管理类实现一个任务队列,根据当前任务执行情况,在限定最大并发数的前提开启新任务,直到清空队列任务的动态过程管理。多用于任务(可能会占用高内存)且多数量(可能导致内存爆炸),和线程池中线程复用是同一个原理。也算是软件开发中具体场景的唯一真解,属于中高阶软件开发展必须掌握的技能。

2、典型场景:批量音视频上传下载,云盘同步等

github

相关推荐
徐同保2 分钟前
n8n+GPT-4o一次解析多张图片
开发语言·前端·javascript
DanyHope9 分钟前
LeetCode 128. 最长连续序列:O (n) 时间的哈希集合 + 剪枝解法全解析
前端·leetcode·哈希算法·剪枝
GISer_Jing14 分钟前
AI赋能前端:从核心概念到工程实践的全景学习指南
前端·javascript·aigc
|晴 天|15 分钟前
前端事件循环:宏任务与微任务的深度解析
前端
走在路上的菜鸟19 分钟前
Android学Dart学习笔记第二十一节 类-点的简写
android·笔记·学习·flutter
不爱吃糖的程序媛23 分钟前
Flutter-OH OAuth 鸿蒙平台适配详细技术文档
javascript·flutter·harmonyos
用户44455436542624 分钟前
Android开发中的封装思路指导
前端
庄雨山32 分钟前
深入解析Flutter动画体系:原理、实战与开源鸿蒙OpenHarmony对比
flutter·openharmonyos
kirk_wang35 分钟前
Flutter GPUImage 库在鸿蒙平台的 GPU 图像滤镜适配实战
flutter·移动开发·跨平台·arkts·鸿蒙
Felixwb66636 分钟前
Python 爬虫框架设计:类封装与工程化实践
前端