fix(mobile): prevent video player from being recreated unnecessarily (#26553)

The changes in #25952 inadvertently removed an optimisation which
prevents the video player from being recreated when the tree changed.
This happens surprisingly often, namely when the hero animation
finishes. The widget is particularly expensive, so recreating it 2-3 in
a short period not only feels sluggish, but also causes the video to
hitch and restart.

The solution is to bring the global key back for the native video
player. Unlike before, we are using a custom global key which compares
the values of hero tags directly. This means we don't need to maintain a
map of hero tags to global keys in the state, and also means we don't
have to pass the global key down multiple layers.

This also fixes #25981.
This commit is contained in:
Thomas
2026-02-27 12:09:38 +00:00
committed by GitHub
parent a100a4025e
commit c2d8400899
2 changed files with 27 additions and 8 deletions

View File

@@ -420,20 +420,18 @@ class NativeVideoViewer extends HookConsumerWidget {
child: Stack(
children: [
// Hide thumbnail once video is visible to avoid it showing in background when zooming out on video.
if (!isVisible.value || controller.value == null) Center(key: ValueKey(asset.heroTag), child: image),
if (!isVisible.value || controller.value == null) Center(child: image),
if (aspectRatio.value != null && !isCasting && isCurrent)
Visibility.maintain(
key: ValueKey(asset),
visible: isVisible.value,
child: PhotoView.customChild(
key: ValueKey(asset),
enableRotation: false,
disableScaleGestures: disableScaleGestures,
// Transparent to avoid a black flash when viewer becomes visible but video isn't loaded yet.
backgroundDecoration: const BoxDecoration(color: Colors.transparent),
scaleStateChangedCallback: (state) => scaleStateNotifier?.value = state,
childSize: videoContextSize(aspectRatio.value, context),
child: NativeVideoPlayerView(key: ValueKey(asset), onViewReady: initController),
child: NativeVideoPlayerView(onViewReady: initController),
),
),
if (showControls) const Center(child: VideoViewerControls()),