fix(mining-app): 更新弹窗点击"立即更新"无反应 — 进度流订阅竞态修复
问题根因: SelfHostedUpdater._listenToProgress() 在 initState 和 _startDownload 中 订阅 UpdateService.downloadProgressStream,但该 getter 返回 _downloadManager?.progressStream —— _downloadManager 在 downloadUpdate() 调用前为 null,?.listen 无操作。downloadUpdate() 创建新 _downloadManager 后,其 progressStream 无人监听,进度事件全部丢失,UI 无任何反馈。 修复: 1. UpdateService 新增持久化广播流 _downloadProgressController, downloadUpdate() 创建新 DownloadManager 后将其进度转发到此流 2. downloadProgressStream getter 改为返回持久化流(非 nullable) 3. SelfHostedUpdater 在 initState 中一次性订阅持久化流, dispose 时取消订阅,_startDownload 不再重复订阅 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
bde7f0c53b
commit
cfa0e2ca40
|
|
@ -1,3 +1,4 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../models/version_info.dart';
|
||||
|
|
@ -48,15 +49,13 @@ class _SelfHostedUpdaterState extends State<SelfHostedUpdater> {
|
|||
DownloadProgress _progress = DownloadProgress.initial();
|
||||
File? _downloadedFile;
|
||||
bool _isDownloading = false;
|
||||
StreamSubscription<DownloadProgress>? _progressSubscription;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_listenToProgress();
|
||||
}
|
||||
|
||||
void _listenToProgress() {
|
||||
UpdateService.instance.downloadProgressStream?.listen((progress) {
|
||||
// 订阅持久化广播流,无论何时开始下载都能收到进度
|
||||
_progressSubscription = UpdateService.instance.downloadProgressStream.listen((progress) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_progress = progress;
|
||||
|
|
@ -65,6 +64,12 @@ class _SelfHostedUpdaterState extends State<SelfHostedUpdater> {
|
|||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_progressSubscription?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _startDownload() async {
|
||||
setState(() {
|
||||
_isDownloading = true;
|
||||
|
|
@ -73,8 +78,6 @@ class _SelfHostedUpdaterState extends State<SelfHostedUpdater> {
|
|||
);
|
||||
});
|
||||
|
||||
_listenToProgress();
|
||||
|
||||
final file = await UpdateService.instance.downloadUpdate(widget.versionInfo);
|
||||
|
||||
if (mounted) {
|
||||
|
|
|
|||
|
|
@ -51,6 +51,10 @@ class UpdateService {
|
|||
final _updateAvailableController = StreamController<VersionInfo?>.broadcast();
|
||||
Stream<VersionInfo?> get updateAvailableStream => _updateAvailableController.stream;
|
||||
|
||||
/// 持久化的下载进度流(跨 DownloadManager 实例保持订阅有效)
|
||||
final _downloadProgressController = StreamController<DownloadProgress>.broadcast();
|
||||
StreamSubscription? _downloadProgressSubscription;
|
||||
|
||||
VersionInfo? _latestVersion;
|
||||
VersionInfo? get latestVersion => _latestVersion;
|
||||
|
||||
|
|
@ -126,14 +130,20 @@ class UpdateService {
|
|||
|
||||
/// 下载更新
|
||||
Future<File?> downloadUpdate(VersionInfo versionInfo) async {
|
||||
// 取消旧的进度转发订阅
|
||||
await _downloadProgressSubscription?.cancel();
|
||||
_downloadManager?.dispose();
|
||||
_downloadManager = DownloadManager(versionInfo: versionInfo);
|
||||
// 将新 DownloadManager 的进度转发到持久化广播流
|
||||
_downloadProgressSubscription = _downloadManager!.progressStream.listen(
|
||||
(progress) => _downloadProgressController.add(progress),
|
||||
);
|
||||
return await _downloadManager!.startDownload();
|
||||
}
|
||||
|
||||
/// 获取下载进度流
|
||||
Stream<DownloadProgress>? get downloadProgressStream =>
|
||||
_downloadManager?.progressStream;
|
||||
/// 获取下载进度流(持久化广播流,订阅后可跨下载任务接收进度)
|
||||
Stream<DownloadProgress> get downloadProgressStream =>
|
||||
_downloadProgressController.stream;
|
||||
|
||||
/// 取消下载
|
||||
void cancelDownload() {
|
||||
|
|
@ -166,7 +176,9 @@ class UpdateService {
|
|||
}
|
||||
|
||||
void dispose() {
|
||||
_downloadProgressSubscription?.cancel();
|
||||
_downloadManager?.dispose();
|
||||
_downloadProgressController.close();
|
||||
_updateAvailableController.close();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue