fix: defer view removal to avoid AOSP dispatchWindowVisibilityChanged NPE

This commit is contained in:
edde746
2026-02-28 10:23:28 +01:00
parent 1bb4adfcf1
commit 014f9456f6
2 changed files with 11 additions and 14 deletions
@@ -1390,23 +1390,21 @@ class ExoPlayerCore(private val activity: Activity) : Player.Listener {
trackSelector = null
assHandler = null
surfaceView?.holder?.removeCallback(surfaceCallback)
val cb = surfaceCallback
val sv = surfaceView
overlayLayoutListener?.let { listener ->
val contentView = activity.findViewById<ViewGroup>(android.R.id.content)
contentView.viewTreeObserver.removeOnGlobalLayoutListener(listener)
}
overlayLayoutListener = null
// Remove SurfaceView from container synchronously — triggers
// onDetachedFromWindow which properly unregisters PositionUpdateListener
// and releases SurfaceControl before the render thread can access it.
// Defer all view removal to avoid AOSP bug where
// dispatchWindowVisibilityChanged iterates stale children array
// when removeView() runs during an active performTraversals pass.
val container = surfaceContainer
surfaceView?.let { container?.removeView(it) }
subtitleView?.let { container?.removeView(it) }
// Defer empty container removal (plain FrameLayout, no SurfaceControl)
val contentView = activity.findViewById<ViewGroup>(android.R.id.content)
contentView.post {
sv?.holder?.removeCallback(cb)
container?.let { contentView.removeView(it) }
}
surfaceContainer = null
@@ -809,15 +809,14 @@ class MpvPlayerCore(private val activity: Activity) :
}
overlayLayoutListener = null
// Remove SurfaceView synchronously (keep callback so surfaceDestroyed
// fires → MPVLib.detachSurface()), then remove callback after.
// Defer all view removal to avoid AOSP bug where
// dispatchWindowVisibilityChanged iterates stale children array
// when removeView() runs during an active performTraversals pass.
val sv = surfaceView
val container = surfaceContainer
surfaceView?.let { container?.removeView(it) }
surfaceView?.holder?.removeCallback(this)
// Defer empty container removal (plain FrameLayout, no SurfaceControl)
val contentView = activity.findViewById<ViewGroup>(android.R.id.content)
contentView.post {
sv?.holder?.removeCallback(this)
container?.let { contentView.removeView(it) }
}
surfaceContainer = null