Ben*_*n H 4 kotlin kotlin-android-extensions kotlin-coroutines
我有很多我的应用程序正常使用"懒惰"初始化程序,因为一切都神奇地按照必要的顺序发生.
但并非所有初始化程序都是同步的.其中一些是包装回调,这意味着我需要等到回调发生,这意味着我需要runBlocking和suspendCoroutine.
但在重构一切后,我明白了 IllegalStateException: runBlocking is not allowed in Android main looper thread
什么?你不能阻止?你在这里杀了我.如果我的"偷懒"恰好是阻挡功能,那么正确的方法是什么?
private val cameraCaptureSession: CameraCaptureSession by lazy {
runBlocking(Background) {
suspendCoroutine { cont: Continuation<CameraCaptureSession> ->
cameraDevice.createCaptureSession(Arrays.asList(readySurface, imageReader.surface), object : CameraCaptureSession.StateCallback() {
override fun onConfigured(session: CameraCaptureSession) {
cont.resume(session).also {
Log.i(TAG, "Created cameraCaptureSession through createCaptureSession.onConfigured")
}
}
override fun onConfigureFailed(session: CameraCaptureSession) {
cont.resumeWithException(Exception("createCaptureSession.onConfigureFailed")).also {
Log.e(TAG, "onConfigureFailed: Could not configure capture session.")
}
}
}, backgroundHandler)
}
}
}
Run Code Online (Sandbox Code Playgroud)
该类的完整GIST,用于了解我最初想要实现的目标:https://gist.github.com/salamanders/aae560d9f72289d5e4b49011fd2ce62b
众所周知,在UI线程上执行阻塞调用会导致在调用期间完全冻结应用程序.createCaptureSession具体国家的文件
完成会话配置可能需要几百毫秒,因为相机硬件可能需要打开电源或重新配置.
它可能很容易导致Application Not Responding对话框和您的应用程序被杀死.这就是为什么Kotlin runBlocking在UI线程上引入了明确的防范.
因此,当您已经尝试访问时,您的想法是及时启动此过程cameraCaptureSession无法工作.你必须做的是将访问它的代码包装进去launch(UI),然后把你val变成一个suspend fun.
简而言之:
private var savedSession: CameraCaptureSession? = null
private suspend fun cameraCaptureSession(): CameraCaptureSession {
savedSession?.also { return it }
return suspendCoroutine { cont ->
cameraDevice.createCaptureSession(listOf(readySurface, imageReader.surface), object : CameraCaptureSession.StateCallback() {
override fun onConfigured(session: CameraCaptureSession) {
savedSession = session
Log.i(TAG, "Created cameraCaptureSession through createCaptureSession.onConfigured")
cont.resume(session)
}
override fun onConfigureFailed(session: CameraCaptureSession) {
Log.e(TAG, "onConfigureFailed: Could not configure capture session.")
cont.resumeWithException(Exception("createCaptureSession.onConfigureFailed"))
}
})
}
}
fun useCamera() {
launch(UI) {
cameraCaptureSession().also { session ->
session.capture(...)
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这session.capture()是包装到的另一个目标suspend fun.
另外请务必注意,如果您确保cameraCaptureSession()在第一次呼叫恢复之前不再呼叫,我给出的代码是安全的.查看后续主题以获得更通用的解决方案.
| 归档时间: |
|
| 查看次数: |
367 次 |
| 最近记录: |