SUBSCRIBE NOW
I always learn something just by skimming it that makes me want to bookmark the issue now and dig deeper later
SUBSCRIBE NOW
Keep up the good work with the newsletter 💪 I really enjoy it
SUBSCRIBE NOW
Dispatch is a must read for Android devs today and my go-to for keeping up with all things Jetpack Compose
SUBSCRIBE NOW
Dispatch has been my go-to resource as it's packed with useful information while being fun at the same time
SUBSCRIBE NOW
The content is light, fun, and still useful. I especially appreciate the small tips that are in each issue
SUBSCRIBE NOW
I truly love this newsletter ❤️🔥 Spot on content and I know there's a lot of effort that goes behind it
SUBSCRIBE NOW
Thanks for taking the time and energy to do it so well
JetpackCompose.app's Newsletter
I always learn something just by skimming it that makes me want to bookmark the issue now and dig deeper later
JetpackCompose.app's Newsletter
Keep up the good work with the newsletter 💪 I really enjoy it
JetpackCompose.app's Newsletter
Dispatch is a must read for Android devs today and my go-to for keeping up with all things Jetpack Compose
JetpackCompose.app's Newsletter
Dispatch has been my go-to resource as it's packed with useful information while being fun at the same time
JetpackCompose.app's Newsletter
The content is light, fun, and still useful. I especially appreciate the small tips that are in each issue
JetpackCompose.app's Newsletter
I truly love this newsletter ❤️🔥 Spot on content and I know there's a lot of effort that goes behind it
JetpackCompose.app's Newsletter
Thanks for taking the time and energy to do it so well
CameraX + Compose
Author: Adam Powell
Sample implementation of CameraX integration in a Composable
suspend fun <R> withChildLifecycleOwner( | |
parentLifecycle: Lifecycle, | |
block: suspend CoroutineScope.(LifecycleOwner) -> R | |
): R { | |
val childOwner = object : LifecycleOwner { | |
val lifecycle = LifecycleRegistry(this) | |
override fun getLifecycle(): Lifecycle = lifecycle | |
} | |
val registry = childOwner.lifecycle | |
return coroutineScope { | |
val myJob = coroutineContext.job | |
val parentObserver = LifecycleEventObserver { _, event -> | |
registry.currentState = event.targetState | |
if (event == Lifecycle.Event.ON_DESTROY) { | |
myJob.cancel("parent lifecycle was destroyed") | |
} | |
} | |
parentLifecycle.addObserver(parentObserver) | |
try { | |
block(childOwner) | |
} finally { | |
parentLifecycle.removeObserver(parentObserver) | |
registry.currentState = Lifecycle.State.DESTROYED | |
} | |
} | |
} | |
class CameraState { | |
private val bindingMutex = MutatorMutex() | |
var camera: Camera? by mutableStateOf(null) | |
private set | |
suspend fun <R> bind( | |
context: Context, | |
lifecycleOwner: LifecycleOwner, | |
selector: CameraSelector, | |
vararg useCases: UseCase, | |
block: suspend (Camera) -> R | |
): R { | |
val provider = ProcessCameraProvider.getInstance(context).await() | |
return bindingMutex.mutate { | |
withChildLifecycleOwner(lifecycleOwner.lifecycle) { childLifecycleOwner -> | |
try { | |
block( | |
provider.bindToLifecycle(childLifecycleOwner, selector, *useCases) | |
.also { this@CameraState.camera = it } | |
) | |
} finally { | |
camera = null | |
} | |
} | |
} | |
} | |
} | |
@Composable | |
fun CameraBinding( | |
state: CameraState, | |
vararg useCases: UseCase, | |
selectorBuilder: CameraSelector.Builder.() -> CameraSelector.Builder = { this } | |
) { | |
// Make selectorBuilder observe snapshot changes and only rebuild the selector | |
// when the builder changes. We do this since selectors don't implement equals | |
// and this makes the API a little nicer since the caller doesn't need | |
// to remember to remember {}. | |
val currentSelectorBuilder by rememberUpdatedState(selectorBuilder) | |
val selector by remember { | |
derivedStateOf { | |
CameraSelector.Builder().run(currentSelectorBuilder).build() | |
} | |
} | |
val lifecycleOwner = LocalLifecycleOwner.current | |
val context = LocalContext.current | |
// useCases.toList() since arrays don't implement structural equality | |
LaunchedEffect(state, selector, lifecycleOwner, useCases.toList()) { | |
state.bind(context, lifecycleOwner, selector, *useCases) { | |
awaitCancellation() | |
} | |
} | |
} |
Have a project you'd like to submit? Fill this form, will ya!
If you like this snippet, you might also like:
Maker OS is an all-in-one productivity system for developers
I built Maker OS to track, manage & organize my life. Now you can do it too!