Joh*_*ohn 5 android android-canvas android-jetpack-compose
在 Jetpack Compose 应用程序中,我有一个缩略图的 LazyVerticalGrid,每个缩略图都需要在撰写时在位图支持的 Canvas 中绘制。
如果我只是在Canvas的DrawScope中绘制缩略图,则可以正确绘制缩略图,但用户体验很差。当用户滚动 LazyVerticalGrid 时,每个缩略图都会自行绘制,因此会出现很多卡顿。
我原以为 Jetpack Compose 在需要时会在后台线程中进行组合,但这一切似乎都发生在主线程上,导致严重的卡顿,即使在最新的手机上也是如此。
我可以通过使用 LaunchedEffect withContext(IO) 在另一个线程上绘制 Canvas 的底层位图来解决卡顿问题。但问题是,Compose 不知道在绘制位图时重新组合 Canvas,所以我经常会得到半绘制的缩略图。
有没有办法在主线程之外完成工作,然后在工作完成后重新组合?
这是 janky 代码(为简洁起见进行了编辑),后面是非 janky 版本,绘图完成后并不总是重新组合:
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())
}
}
Run Code Online (Sandbox Code Playgroud)
不卡顿但仍然不对
val imageBitmap = remember {Bitmap.createBitmap(515, 618, Bitmap.Config.ARGB_8888)}
val bitmapCanvas = remember { android.graphics.Canvas(imageBitmap) }
LaunchedEffect(Unit) {
withContext(IO) {
bitmapCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
penStrokes.forEach {
inker.drawEvent(it)
}
}
}
ElevatedCard() {
Canvas() {
this.drawImage(imageBitmap.asImageBitmap())
}
}
Run Code Online (Sandbox Code Playgroud)
最后,我使用了常见的“invalidate++”拼凑,人们似乎用它来强制 Jetpack Compose 根据命令重绘。我认为它有一点代码味道,但它确实有效。
val imageBitmap = remember {Bitmap.createBitmap(515, 618,
Bitmap.Config.ARGB_8888)}
val bitmapCanvas = remember { android.graphics.Canvas(imageBitmap) }
var invalidate by remember { mutableStateOf(0) }
LaunchedEffect(Unit) {
withContext(IO) {
bitmapCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
penStrokes.forEach {
inker.drawEvent(it)
}
invalidate++
}
}
ElevatedCard() {
Canvas() {
invalidate.let {
this.drawImage(imageBitmap.asImageBitmap())
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2723 次 |
| 最近记录: |