How to do work off the main thread in Jetpack Compose?
In a Jetpack Compose app I have a LazyVerticalGrid of thumbnails, each of which needs to be drawn in a bitmap-backed Canvas at compose time.
The thumbnails draw correctly if I simply draw them in DrawScope of the Canvas, but the user experience is poor. When the user scrolls the LazyVerticalGrid, there is a lot of jank as each thumbnail draws itself.
I had through that Jetpack Compose composed in background threads when needed, but it all seems to be happening in the main thread, leading to the severe jank, even on the latest phones.
I can solve the jank problem by drawing onto the Canvas's underlying bitmap on another thread, using LaunchedEffect withContext(IO). But the problem is, Compose doesn't know to recompose the Canvas when the bitmap is drawn, so I often end up with half-drawn thumbnails.
Is there a way to do work off the main thread and then recompose once that work is done?
Here is the janky code (edited for brevity), followed by the non-janky version that doesn't always recompose when the drawing is complete:
val imageBitmap = remember {Bitmap.createBitmap(515, 618, Bitmap.Config.ARGB_8888)}
val bitmapCanvas = remember { android.graphics.Canvas(imageBitmap) }
ElevatedCard() {
Canvas() {
bitmapCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
penStrokes.forEach {
inker.drawEvent(it)
}
this.drawImage(imageBitmap.asImageBitmap())
}
}
non-janky but still not right
val imageBitmap = remember {Bitmap.createBitmap(515, 618, Bitmap.Config.ARGB_8888)}
val bitmapCanvas = remember { android.graphics.Canvas(imageBitmap) }
LaunchedEffect(Unit) {
bitmapCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
penStrokes.forEach {
inker.drawEvent(it)
}
}
ElevatedCard() {
Canvas() {
this.drawI开发者_如何学Cmage(imageBitmap.asImageBitmap())
}
}
精彩评论