Dart类中静态字段downloadFinishedCallbacks为何会为空?
FlutterDownloader回调中静态Map为空的原因与解决方法
问题根源
flutter_downloader的回调函数(downloadCallback)是运行在独立的Isolate中的,和主业务代码不在同一个内存空间。Dart里不同Isolate的静态变量完全隔离——你在主Isolate里往downloadFinishedCallbacks添加的键值对,回调所在的Isolate根本访问不到,所以触发回调时Map自然是空的。
解决思路
跨Isolate不能直接共享静态变量,得用Dart的Isolate通信机制:通过SendPort和ReceivePort让回调Isolate把下载状态信息传递给主Isolate,再由主Isolate执行对应的回调逻辑。
修改后的代码实现
import 'package:flutter_downloader/flutter_downloader.dart'; import 'package:synchronized/synchronized.dart'; import 'dart:isolate'; class DownloaderHelper { // 用于跨Isolate通信的SendPort,由主Isolate初始化 static SendPort? _mainSendPort; static final Lock _lock = Lock(); static void initializeDownloader() async { await FlutterDownloader.initialize( debug: false, ignoreSsl: true, ); // 创建ReceivePort接收回调Isolate的消息 final receivePort = ReceivePort(); _mainSendPort = receivePort.sendPort; // 监听消息,处理下载完成/失败逻辑 receivePort.listen((message) { if (message is Map) { final id = message['id'] as String; final status = DownloadTaskStatus.fromInt(message['status'] as int); _handleDownloadFinished(id, status); } }); FlutterDownloader.registerCallback(downloadCallback); } // 主Isolate中维护回调映射,保证访问安全 static final Map<String, void Function(DownloadTaskStatus)> _downloadCallbacks = {}; static void registerDownloadFinishedCallback(String id, void Function(DownloadTaskStatus) callback) { _lock.synchronized(() { _downloadCallbacks[id] = callback; }); } // 主Isolate内执行回调逻辑 static void _handleDownloadFinished(String id, DownloadTaskStatus status) { _lock.synchronized(() { _downloadCallbacks[id]?.call(status); _downloadCallbacks.remove(id); }); } // 回调运行在独立Isolate,仅负责向主Isolate发送状态消息 static void downloadCallback(String id, int status, int progress) { print('Download callback: ID = ${id}, status = ${status}, progress = ${progress}'); final taskStatus = DownloadTaskStatus.fromInt(status); if (taskStatus == DownloadTaskStatus.complete || taskStatus == DownloadTaskStatus.failed) { _mainSendPort?.send({ 'id': id, 'status': status, }); } } }
核心改动说明
- 拆分回调逻辑:回调Isolate只做状态上报,主Isolate负责维护回调Map并执行回调。
- 用
ReceivePort和SendPort实现跨Isolate通信,绕过内存隔离限制。 - 保留
Lock确保主Isolate内操作Map的线程安全。
内容的提问来源于stack exchange,提问作者Vitalii
相关产品推荐
相关产品推荐

