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 'dart:io';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '../models/version_info.dart';
|
import '../models/version_info.dart';
|
||||||
|
|
@ -48,15 +49,13 @@ class _SelfHostedUpdaterState extends State<SelfHostedUpdater> {
|
||||||
DownloadProgress _progress = DownloadProgress.initial();
|
DownloadProgress _progress = DownloadProgress.initial();
|
||||||
File? _downloadedFile;
|
File? _downloadedFile;
|
||||||
bool _isDownloading = false;
|
bool _isDownloading = false;
|
||||||
|
StreamSubscription<DownloadProgress>? _progressSubscription;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_listenToProgress();
|
// 订阅持久化广播流,无论何时开始下载都能收到进度
|
||||||
}
|
_progressSubscription = UpdateService.instance.downloadProgressStream.listen((progress) {
|
||||||
|
|
||||||
void _listenToProgress() {
|
|
||||||
UpdateService.instance.downloadProgressStream?.listen((progress) {
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_progress = progress;
|
_progress = progress;
|
||||||
|
|
@ -65,6 +64,12 @@ class _SelfHostedUpdaterState extends State<SelfHostedUpdater> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_progressSubscription?.cancel();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _startDownload() async {
|
Future<void> _startDownload() async {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isDownloading = true;
|
_isDownloading = true;
|
||||||
|
|
@ -73,8 +78,6 @@ class _SelfHostedUpdaterState extends State<SelfHostedUpdater> {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
_listenToProgress();
|
|
||||||
|
|
||||||
final file = await UpdateService.instance.downloadUpdate(widget.versionInfo);
|
final file = await UpdateService.instance.downloadUpdate(widget.versionInfo);
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,10 @@ class UpdateService {
|
||||||
final _updateAvailableController = StreamController<VersionInfo?>.broadcast();
|
final _updateAvailableController = StreamController<VersionInfo?>.broadcast();
|
||||||
Stream<VersionInfo?> get updateAvailableStream => _updateAvailableController.stream;
|
Stream<VersionInfo?> get updateAvailableStream => _updateAvailableController.stream;
|
||||||
|
|
||||||
|
/// 持久化的下载进度流(跨 DownloadManager 实例保持订阅有效)
|
||||||
|
final _downloadProgressController = StreamController<DownloadProgress>.broadcast();
|
||||||
|
StreamSubscription? _downloadProgressSubscription;
|
||||||
|
|
||||||
VersionInfo? _latestVersion;
|
VersionInfo? _latestVersion;
|
||||||
VersionInfo? get latestVersion => _latestVersion;
|
VersionInfo? get latestVersion => _latestVersion;
|
||||||
|
|
||||||
|
|
@ -126,14 +130,20 @@ class UpdateService {
|
||||||
|
|
||||||
/// 下载更新
|
/// 下载更新
|
||||||
Future<File?> downloadUpdate(VersionInfo versionInfo) async {
|
Future<File?> downloadUpdate(VersionInfo versionInfo) async {
|
||||||
|
// 取消旧的进度转发订阅
|
||||||
|
await _downloadProgressSubscription?.cancel();
|
||||||
_downloadManager?.dispose();
|
_downloadManager?.dispose();
|
||||||
_downloadManager = DownloadManager(versionInfo: versionInfo);
|
_downloadManager = DownloadManager(versionInfo: versionInfo);
|
||||||
|
// 将新 DownloadManager 的进度转发到持久化广播流
|
||||||
|
_downloadProgressSubscription = _downloadManager!.progressStream.listen(
|
||||||
|
(progress) => _downloadProgressController.add(progress),
|
||||||
|
);
|
||||||
return await _downloadManager!.startDownload();
|
return await _downloadManager!.startDownload();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 获取下载进度流
|
/// 获取下载进度流(持久化广播流,订阅后可跨下载任务接收进度)
|
||||||
Stream<DownloadProgress>? get downloadProgressStream =>
|
Stream<DownloadProgress> get downloadProgressStream =>
|
||||||
_downloadManager?.progressStream;
|
_downloadProgressController.stream;
|
||||||
|
|
||||||
/// 取消下载
|
/// 取消下载
|
||||||
void cancelDownload() {
|
void cancelDownload() {
|
||||||
|
|
@ -166,7 +176,9 @@ class UpdateService {
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
_downloadProgressSubscription?.cancel();
|
||||||
_downloadManager?.dispose();
|
_downloadManager?.dispose();
|
||||||
|
_downloadProgressController.close();
|
||||||
_updateAvailableController.close();
|
_updateAvailableController.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue