簡體   English   中英

為什么 Kotlin 中某些 GlobalScope.launch 調用的內容默默地無法執行?

[英]Why are the contents of some GlobalScope.launch calls in Kotlin silently failing to execute?

我是 Kotlin 的新手——事實上,我從來沒有打算使用它,但我正在嘗試使用CameraKit庫,它使用似乎是生成的 Kotlin 層作為其 API 接口。 我一直遇到相機未正確斷開連接的問題,有問題的代碼(或至少在我看來最相關的部分)如下所示:

class CameraPreview : FrameLayout, CameraEvents {
    var TAG = "CameraPreview.kt"
    var lifecycleState: LifecycleState = LifecycleState.STOPPED
    var surfaceState: SurfaceState = SurfaceState.SURFACE_WAITING
    var cameraState: CameraState = CameraState.CAMERA_CLOSED
        set(state) {
            field = state
            when (state) {
                CameraState.CAMERA_OPENED -> {
                    listener?.onCameraOpened()
                }
                CameraState.PREVIEW_STARTED -> {
                    listener?.onPreviewStarted()
                }
                CameraState.PREVIEW_STOPPED -> {
                    listener?.onPreviewStopped()
                }
                CameraState.CAMERA_CLOSING -> {
                    listener?.onCameraClosed()
                }
                else -> {
                    // ignore
                }
            }
        }


    private val cameraDispatcher: CoroutineDispatcher = newSingleThreadContext("CAMERA")
    private var cameraOpenContinuation: Continuation<Unit>? = null
    private var previewStartContinuation: Continuation<Unit>? = null


    init {
        val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        displayOrientation = windowManager.defaultDisplay.rotation * 90

        cameraSurfaceView.cameraSurfaceTextureListener = object : CameraSurfaceTextureListener {
            override fun onSurfaceReady(cameraSurfaceTexture: CameraSurfaceTexture) {
                surfaceTexture = cameraSurfaceTexture
                surfaceState = SurfaceState.SURFACE_AVAILABLE
                if (lifecycleState == LifecycleState.STARTED || lifecycleState == LifecycleState.RESUMED) {
                    resume()
                }
            }
        }

        addView(cameraSurfaceView)
    }

    fun start(facing: CameraFacing) {
        GlobalScope.launch(cameraDispatcher) {
            runBlocking {
                Log.i(TAG, "Start preview state is "+lifecycleState)
                lifecycleState = LifecycleState.STARTED
                cameraFacing = facing
                openCamera()
            }
        }
    }

    fun resume() {
        GlobalScope.launch(cameraDispatcher) {
            runBlocking {
                Log.i("CameraPreview.kt", "Resume preview state is "+lifecycleState)
                lifecycleState = LifecycleState.RESUMED
                try {
                    startPreview()
                } catch (e: Exception) {
                    Log.i("CameraPreview.kt", "Start preview hit an exception: "+e.message)
                    // camera or surface not ready, wait.
                }
            }
        }
    }

    fun pause() {
        Log.i("CameraPreview.kt", "Pause called");
        GlobalScope.launch(cameraDispatcher) {
            Log.i(TAG, "Pause scope launched, runblocking call ahead.")
            runBlocking {
                Log.i("CameraPreview.kt", "Pause initiated, stop preview state is "+lifecycleState)
                lifecycleState = LifecycleState.PAUSED
                stopPreview()
            }  
        }

    }

    fun stop() {
        Log.i("CameraPreview.kt", "Stop called");
        GlobalScope.launch(cameraDispatcher) {
            Log.i(TAG, "Stop scope launched, runblocking call ahead.")
            runBlocking {
                Log.i("CameraPreview.kt", "Stop initiated, close camera state is "+lifecycleState)
                lifecycleState = LifecycleState.STOPPED
                closeCamera()
            }

        }

    }



    enum class CameraState {
        CAMERA_OPENING,
        CAMERA_OPENED,
        PREVIEW_STARTING,
        PREVIEW_STARTED,
        PREVIEW_STOPPING,
        PREVIEW_STOPPED,
        CAMERA_CLOSING,
        CAMERA_CLOSED;
    }

    // Camera control:

    private suspend fun openCamera(): Unit = suspendCoroutine {
        cameraOpenContinuation = it
        cameraState = CameraState.CAMERA_OPENING
        Log.i("CameraPreview.kt", "openCamera call state is "+lifecycleState)
        cameraApi.open(cameraFacing)
    }

    private suspend fun startPreview(): Unit = suspendCoroutine {
        Log.i("CameraPreview.kt", "startPreview, lifecyclestate "+ lifecycleState);
        // do stuff

    }

    private suspend fun stopPreview(): Unit = suspendCoroutine {
        Log.i("CameraPreview.kt", "Stop preview state is "+lifecycleState)
        cameraState = CameraState.PREVIEW_STOPPING
        cameraApi.stopPreview()
        it.resume(Unit)
    }

    private suspend fun closeCamera(): Unit = suspendCoroutine {
        Log.i("CameraPreview.kt", "Close camera state is "+lifecycleState)
        cameraState = CameraState.CAMERA_CLOSING
        cameraApi.release()
        it.resume(Unit)
    }


}

現在,當startresume被調用時,他們會做他們應該做的事情。 調用pausestop ,沒有可感知的變化,相機預覽既不暫停也不停止。

我的日志記錄表明,在調用pause()時,會記錄初始調用,但GlobalScope.launch(cameraDispatcher)的日志語句從未出現。 似乎 GlobalScope 只是將協同程序啟動到了虛空中。 startresume工作時,呼叫或調度員似乎沒有問題,但很難知道還能在哪里查看

如果我將pausestop協程的內容放在GlobalScope.launch之外以創建如下內容:

fun pause() {
    Log.i("CameraPreview.kt", "Pause called");
    GlobalScope.launch(cameraDispatcher) {
        Log.i(TAG, "Pause scope launched, runblocking call ahead.")
        runBlocking {
            Log.i("CameraPreview.kt", "Pause initiated, stop preview state is "+lifecycleState)
            lifecycleState = LifecycleState.PAUSED
            stopPreview()
        }
    }
    cameraState = CameraState.PREVIEW_STOPPING
    cameraApi.stopPreview()
}

它不僅現在可以工作,而且協程也開始處理后續調用,就好像被調用的內容以某種方式讓它卡住了。 運行時,我在 Logcat 中看不到任何錯誤消息。

這是我對 Kotlin 的第一次介紹,所以我不完全確定它應該如何工作,但似乎完全繞過基本代碼可能不是規范的一部分。 任何人都可以建議這里發生了什么,或者我如何追蹤問題的真正根源?

問題可能是您正在使用帶有cameraDispatcher的共享單線程調度cameraDispatcher ,然后您使用runBlocking阻止runBlocking 我不確定這段代碼基於什么,但runBlocking在其文檔中有一個警告,它應該只在協程和嚴格線程綁定的執行(如main或測試框架)之間進行橋接時使用。

如果您刪除對runBlocking所有調用,您的代碼應該仍然有效

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM