From bb10a75f0e0c2b8db42ee14cd853a6ce7c656736 Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Tue, 22 Oct 2024 12:47:13 +0800 Subject: [PATCH] fix: use internal Set for determining first ThermionTextureWidget to call requestFrame and cleanup destruction logic --- .../widgets/src/thermion_texture_widget.dart | 39 ++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/thermion_flutter/thermion_flutter/lib/src/widgets/src/thermion_texture_widget.dart b/thermion_flutter/thermion_flutter/lib/src/widgets/src/thermion_texture_widget.dart index 840f02f7..ae4c982d 100644 --- a/thermion_flutter/thermion_flutter/lib/src/widgets/src/thermion_texture_widget.dart +++ b/thermion_flutter/thermion_flutter/lib/src/widgets/src/thermion_texture_widget.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:logging/logging.dart'; import 'package:thermion_dart/src/viewer/src/shared_types/view.dart' as t; import 'package:thermion_flutter/src/widgets/src/resize_observer.dart'; import 'package:thermion_flutter/thermion_flutter.dart'; @@ -42,15 +43,17 @@ class ThermionTextureWidget extends StatefulWidget { class _ThermionTextureWidgetState extends State { ThermionFlutterTexture? _texture; - RenderTarget? _renderTarget; static final _views = []; + final _logger = Logger("_ThermionTextureWidgetState"); + @override void dispose() { super.dispose(); _views.remove(widget.view); _texture?.destroy(); + _states.remove(this); } @override @@ -79,14 +82,16 @@ class _ThermionTextureWidgetState extends State { widget.view, dpr); } catch (err, st) { - print(err); - print(st); + _logger.severe(err); + _logger.severe(st); } if (mounted) { setState(() {}); } + _states.add(this); + _requestFrame(); widget.viewer.onDispose(() async { @@ -98,23 +103,39 @@ class _ThermionTextureWidgetState extends State { _views.clear(); }); }); - _callbackId = _numCallbacks; - _numCallbacks++; super.initState(); } bool _rendering = false; - static int _numCallbacks = 0; - static int _primaryCallback = 0; - late int _callbackId; + static final _states = <_ThermionTextureWidgetState>{}; + int lastRender = 0; + /// + /// Each instance of ThermionTextureWidget in the widget hierarchy must + /// call[markFrameAvailable] on every frame to notify Flutter that the content + /// of its backing texture has changed. + /// + /// Calling [requestFrame] on [ThermionViewer], however, will render all + /// views/swapchains that have been marked as renderable (see [setRenderable]). + /// + /// Only need one instance of [ThermionTextureWidget] needs to call + /// [requestFrame]. We manage this by storing all instances of + /// [_ThermionTextureWidgetState] in a static set, and allowing the first + /// instance to call [requestFrame]. + /// void _requestFrame() { + if (!mounted) { + return; + } WidgetsBinding.instance.scheduleFrameCallback((d) async { + if (!mounted) { + return; + } if (widget.viewer.rendering && !_rendering) { _rendering = true; - if (_callbackId == _primaryCallback && _texture != null) { + if (this == _states.first && _texture != null) { await widget.viewer.requestFrame(); lastRender = d.inMilliseconds; }