feat(app): 激活模型变化时重建推理 worker(无模型仅预览并提示选择)
ModelManager 激活集变化(下载完成自动激活/取消激活/目录刷新)时经 _onModelsChanged 触发 _reloadWorker:激活集未变直接跳过,变了则重建 worker+analyzer 并重启帧流;无激活模型时仅预览,横幅区分 「未使用模型:点右上角设置…」与「识别模型加载失败…」。
This commit is contained in:
@@ -38,6 +38,10 @@ class _CameraScreenState extends State<CameraScreen> {
|
||||
Map<dynamic, dynamic> _nativeStats = const {};
|
||||
Timer? _statsTimer;
|
||||
|
||||
/// 当前 worker 已加载的模型 id 集合(激活集变化对比用)
|
||||
Set<int> _loadedModelIds = const {};
|
||||
bool _reloadingWorker = false;
|
||||
|
||||
void _openSettings() {
|
||||
final vm = _viewModel;
|
||||
if (vm == null) return;
|
||||
@@ -116,6 +120,8 @@ class _CameraScreenState extends State<CameraScreen> {
|
||||
WakelockPlus.enable();
|
||||
// 每秒轮询原生侧帧状态:无帧时诊断行也能实时刷新(camErr/计数)
|
||||
_statsTimer = Timer.periodic(const Duration(seconds: 1), (_) => _pollStats());
|
||||
// 模型清单激活集变化(下载完成自动激活/取消激活)时重建推理 worker
|
||||
ModelManager.instance.addListener(_onModelsChanged);
|
||||
}
|
||||
|
||||
Future<void> _pollStats() async {
|
||||
@@ -132,8 +138,7 @@ class _CameraScreenState extends State<CameraScreen> {
|
||||
setState(() => _permissionGranted = granted);
|
||||
if (!granted) return;
|
||||
|
||||
// 模型热更新:优先使用已下载的数据集模型(启动时后台拉取;此处兜底等待,
|
||||
// 下载慢/失败不阻塞相机启动——无下载模型时仅预览)
|
||||
// 模型热更新:启动拉取目录(只拉不下载),此处兜底等待;未下载模型时仅预览
|
||||
if (!ModelManager.instance.ready) {
|
||||
try {
|
||||
await ModelManager.instance
|
||||
@@ -141,23 +146,55 @@ class _CameraScreenState extends State<CameraScreen> {
|
||||
.timeout(const Duration(seconds: 15));
|
||||
} catch (_) {}
|
||||
}
|
||||
// 模型加载/推理在后台 isolate,不阻塞 UI;worker 为 null 时仅预览并提示
|
||||
final worker = await DetectorWorker.create(
|
||||
models: ModelManager.instance.models);
|
||||
final viewModel = CameraViewModel(reminder: Reminder());
|
||||
viewModel.setModelReady(worker != null);
|
||||
final analyzer = FrameAnalyzer(worker: worker, viewModel: viewModel);
|
||||
if (!mounted) {
|
||||
analyzer.dispose();
|
||||
viewModel.dispose();
|
||||
await _reloadWorker();
|
||||
await _startCamera();
|
||||
}
|
||||
|
||||
/// 用当前激活模型重建推理 worker(激活集变化/启动时调用);
|
||||
/// worker 为 null(无激活模型或加载失败)时仅预览并提示。
|
||||
Future<void> _reloadWorker() async {
|
||||
if (_reloadingWorker) return;
|
||||
_reloadingWorker = true;
|
||||
try {
|
||||
final models = ModelManager.instance.models;
|
||||
final ids = models.map((m) => m.datasetId).toSet();
|
||||
if (_viewModel != null &&
|
||||
_loadedModelIds.length == ids.length &&
|
||||
_loadedModelIds.containsAll(ids)) {
|
||||
return; // 激活集未变(进度/目录刷新通知)直接跳过
|
||||
}
|
||||
final worker = await DetectorWorker.create(models: models);
|
||||
_loadedModelIds = ids;
|
||||
final vm = _viewModel ?? CameraViewModel(reminder: Reminder());
|
||||
vm.setModelReady(worker != null);
|
||||
final analyzer = FrameAnalyzer(worker: worker, viewModel: vm);
|
||||
final old = _analyzer;
|
||||
if (!mounted) {
|
||||
analyzer.dispose();
|
||||
if (vm != _viewModel) vm.dispose();
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
_viewModel = vm;
|
||||
_analyzer = analyzer;
|
||||
});
|
||||
old?.worker?.dispose();
|
||||
// 相机已启动:重启帧流绑定新 analyzer(start 内部先 stop 再订阅)
|
||||
if (mounted && _cameraController != null) {
|
||||
await _cameraController!.start(analyzer);
|
||||
}
|
||||
} finally {
|
||||
_reloadingWorker = false;
|
||||
}
|
||||
}
|
||||
|
||||
void _onModelsChanged() {
|
||||
final ids = ModelManager.instance.models.map((m) => m.datasetId).toSet();
|
||||
if (_loadedModelIds.length == ids.length &&
|
||||
_loadedModelIds.containsAll(ids)) {
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
_viewModel = viewModel;
|
||||
_analyzer = analyzer;
|
||||
});
|
||||
|
||||
await _startCamera();
|
||||
_reloadWorker();
|
||||
}
|
||||
|
||||
Future<void> _startCamera() async {
|
||||
@@ -193,6 +230,7 @@ class _CameraScreenState extends State<CameraScreen> {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
ModelManager.instance.removeListener(_onModelsChanged);
|
||||
_statsTimer?.cancel();
|
||||
WakelockPlus.disable();
|
||||
_cameraController?.stop();
|
||||
@@ -333,7 +371,9 @@ class _CameraScreenState extends State<CameraScreen> {
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(
|
||||
'识别模型加载失败:${DetectorWorker.lastLoadError ?? '未知原因'}\n最后步骤:${DetectorWorker.lastLog ?? '-'}',
|
||||
ModelManager.instance.models.isEmpty
|
||||
? '未使用模型:点右上角设置,在「模型清单」中选择要使用的模型'
|
||||
: '识别模型加载失败:${DetectorWorker.lastLoadError ?? '未知原因'}\n最后步骤:${DetectorWorker.lastLog ?? '-'}',
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(color: Colors.orange, fontSize: 14),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user