Move capture callbacks to background executor

Replace ContextCompat.getMainExecutor with a dedicated single-thread
executor for image capture callbacks. This prevents bitmap decode,
rotation, and tilt-shift effect processing from blocking the UI thread
and causing jank or ANR on slower devices.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2026-03-05 12:08:00 +01:00
commit 04b61fdd9e

View file

@ -19,6 +19,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import java.util.concurrent.Executor
import java.util.concurrent.Executors
/**
* Manages CameraX camera setup and controls.
@ -56,6 +57,9 @@ class CameraManager(private val context: Context) {
private val _isFrontCamera = MutableStateFlow(false)
val isFrontCamera: StateFlow<Boolean> = _isFrontCamera.asStateFlow()
/** Background executor for image capture callbacks to avoid blocking the main thread. */
private val captureExecutor: Executor = Executors.newSingleThreadExecutor()
private var surfaceTextureProvider: (() -> SurfaceTexture?)? = null
private var surfaceSize: Size = Size(1920, 1080)
private var lifecycleOwnerRef: LifecycleOwner? = null
@ -194,10 +198,12 @@ class CameraManager(private val context: Context) {
}
/**
* Gets the executor for image capture callbacks.
* Gets the background executor for image capture callbacks.
* Uses a dedicated thread to avoid blocking the main/UI thread during heavy
* bitmap processing (decode, rotate, tilt-shift effect).
*/
fun getExecutor(): Executor {
return ContextCompat.getMainExecutor(context)
return captureExecutor
}
/**