tl/dr: Can “by lazy” be used in constructors that aren’t finished until a callback completes (which requires suspendCoroutine)?
I’m so close I can taste it!
The Android camera2 API isn’t easy - it requires a careful choreographed dance of callbacks, attaching listeners, waiting for onReady states, etc. So I tried a completely different experiment, breaking down everything into small “by lazy” chunks, and relying on the dependencies to magically initialize everything in the right order through a giant implied cascading dependency graph.
A bit crazy, but I had an excellent “deconstructed” dish at a fancy restaurant, and got inspired.
Most of it is easy. The builders that wrap callbacks are harder, I ended up with
/** The surface that the preview gets drawn on */
private val readySurface: Surface by lazy {
runBlocking(bgThreadPoolContext) {
suspendCoroutine { cont: Continuation<Surface> ->
if (previewTextureView.isAvailable) {
cont.resume(Surface(previewTextureView.surfaceTexture)).also {
Log.i(TAG, "Created readySurface directly")
}
} else ....
But I get IllegalStateException: runBlocking is not allowed in Android main looper thread
Huh? Then where can I run it? Is what I’m trying to do impossible? I was very hopeful that the dependency graph would magically auto-resolve itself. I’m ok with the UI having to wait a few seconds until the camera spins up.
Public Gist that shows what I was attempting to do: Deconstructed Camera2 · GitHub