fix: Improve Android resource efficiency/cleanup (use class members for CoroutineScope and FrameProcessorThread) (#335)
* fix: Use custom CoroutineScope * fix: Use custom `CoroutineScope` * Make `frameProcessorThread` and `coroutineScope` instance variables * Update VisionCameraScheduler.java * Remove `HybridData::resetNative()` calls they're called by a Java GC destructor anyways. * Update CameraViewManager.kt * Update CameraView.kt
This commit is contained in:
@@ -27,6 +27,7 @@ import com.mrousavy.camera.utils.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.guava.await
|
||||
import java.lang.IllegalArgumentException
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
@@ -60,8 +61,16 @@ import kotlin.math.min
|
||||
// TODO: takePhoto() return with jsi::Value Image reference for faster capture
|
||||
|
||||
@Suppress("KotlinJniMissingFunction") // I use fbjni, Android Studio is not smart enough to realize that.
|
||||
@SuppressLint("ClickableViewAccessibility") // suppresses the warning that the pinch to zoom gesture is not accessible
|
||||
class CameraView(context: Context) : FrameLayout(context), LifecycleOwner {
|
||||
@SuppressLint("ClickableViewAccessibility", "ViewConstructor")
|
||||
class CameraView(context: Context, private val frameProcessorThread: ExecutorService) : FrameLayout(context), LifecycleOwner {
|
||||
companion object {
|
||||
const val TAG = "CameraView"
|
||||
const val TAG_PERF = "CameraView.performance"
|
||||
|
||||
private val propsThatRequireSessionReconfiguration = arrayListOf("cameraId", "format", "fps", "hdr", "lowLightBoost", "photo", "video", "enableFrameProcessor")
|
||||
private val arrayListOfZoom = arrayListOf("zoom")
|
||||
}
|
||||
|
||||
// react properties
|
||||
// props that require reconfiguring
|
||||
var cameraId: String? = null // this is actually not a react prop directly, but the result of setting device={}
|
||||
@@ -95,6 +104,7 @@ class CameraView(context: Context) : FrameLayout(context), LifecycleOwner {
|
||||
private val cameraExecutor = Executors.newSingleThreadExecutor()
|
||||
internal val takePhotoExecutor = Executors.newSingleThreadExecutor()
|
||||
internal val recordVideoExecutor = Executors.newSingleThreadExecutor()
|
||||
private var coroutineScope = CoroutineScope(Dispatchers.Main)
|
||||
|
||||
internal var camera: Camera? = null
|
||||
internal var imageCapture: ImageCapture? = null
|
||||
@@ -172,7 +182,6 @@ class CameraView(context: Context) : FrameLayout(context), LifecycleOwner {
|
||||
scaleGestureDetector = ScaleGestureDetector(context, scaleGestureListener)
|
||||
touchEventListener = OnTouchListener { _, event -> return@OnTouchListener scaleGestureDetector.onTouchEvent(event) }
|
||||
|
||||
|
||||
hostLifecycleState = Lifecycle.State.INITIALIZED
|
||||
lifecycleRegistry = LifecycleRegistry(this)
|
||||
reactContext.addLifecycleEventListener(object : LifecycleEventListener {
|
||||
@@ -206,10 +215,6 @@ class CameraView(context: Context) : FrameLayout(context), LifecycleOwner {
|
||||
}
|
||||
}
|
||||
|
||||
fun finalize() {
|
||||
mHybridData.resetNative()
|
||||
}
|
||||
|
||||
private external fun initHybrid(): HybridData
|
||||
private external fun frameProcessorCallback(frame: ImageProxy)
|
||||
|
||||
@@ -252,8 +257,8 @@ class CameraView(context: Context) : FrameLayout(context), LifecycleOwner {
|
||||
fun update(changedProps: ArrayList<String>) = previewView.post {
|
||||
// TODO: Does this introduce too much overhead?
|
||||
// I need to .post on the previewView because it might've not been initialized yet
|
||||
// I need to use GlobalScope.launch because of the suspend fun [configureSession]
|
||||
GlobalScope.launch(Dispatchers.Main) {
|
||||
// I need to use CoroutineScope.launch because of the suspend fun [configureSession]
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
val shouldReconfigureSession = changedProps.containsAny(propsThatRequireSessionReconfiguration)
|
||||
val shouldReconfigureZoom = shouldReconfigureSession || changedProps.contains("zoom")
|
||||
@@ -334,7 +339,7 @@ class CameraView(context: Context) : FrameLayout(context), LifecycleOwner {
|
||||
val imageAnalysisBuilder = ImageAnalysis.Builder()
|
||||
.setTargetRotation(rotation)
|
||||
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
|
||||
.setBackgroundExecutor(CameraViewModule.FrameProcessorThread)
|
||||
.setBackgroundExecutor(frameProcessorThread)
|
||||
|
||||
if (format == null) {
|
||||
// let CameraX automatically find best resolution for the target aspect ratio
|
||||
@@ -473,12 +478,4 @@ class CameraView(context: Context) : FrameLayout(context), LifecycleOwner {
|
||||
}
|
||||
return map
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "CameraView"
|
||||
const val TAG_PERF = "CameraView.performance"
|
||||
|
||||
private val propsThatRequireSessionReconfiguration = arrayListOf("cameraId", "format", "fps", "hdr", "lowLightBoost", "photo", "video", "enableFrameProcessor")
|
||||
private val arrayListOfZoom = arrayListOf("zoom")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user