diff --git a/flutter_app/lib/models/model_manager.dart b/flutter_app/lib/models/model_manager.dart index 08241ed..ddccbdd 100644 --- a/flutter_app/lib/models/model_manager.dart +++ b/flutter_app/lib/models/model_manager.dart @@ -123,7 +123,7 @@ class ModelManager extends ChangeNotifier { /// 是否成功拉取过目录(即使下载失败也为 true,用于区分"从未联网"与"目录为空") bool get ready => _ready; - /// 最近一次同步的错误信息(下载失败/校验失败等;目录为空不算错误) + /// 模型目录拉取失败的错误信息(仅目录级;下载/校验失败见 errorOf) String? get error => _error; bool get refreshing => _refreshing; @@ -206,6 +206,10 @@ class ModelManager extends ChangeNotifier { /// 成功自动加入激活集(下载完成即使用)。失败重试一次并记录错误。 Future downloadModel(ModelCatalogItem item, {void Function(int received, int total)? onProgress}) async { + // 并发保护:同一数据集已有进行中的下载则直接短路(预置 0 先占位, + // 使 onProgress 首次回调前的双击/refresh 交错也被 containsKey 拦下) + if (_progress.containsKey(item.datasetId)) return false; + _progress[item.datasetId] = 0; final dir = await _modelDir(item.datasetId); final file = File('${dir.path}/model.tflite'); try { @@ -252,7 +256,10 @@ class ModelManager extends ChangeNotifier { final res = await _client .send(http.Request('GET', Uri.parse('$baseUrl${item.downloadUrl}'))) .timeout(const Duration(minutes: 3)); - if (res.statusCode != 200) return false; + if (res.statusCode != 200) { + await sink.close(); + return false; + } final total = res.contentLength ?? item.sizeBytes; await for (final chunk in res.stream) { sink.add(chunk);