【问题标题】:How to do work off the main thread in Jetpack Compose?如何在 Jetpack Compose 中关闭主线程?
【发布时间】:2022-12-21 12:07:52
【问题描述】:

在 Jetpack Compose 应用程序中,我有一个 LazyVerticalGrid 缩略图,每个缩略图都需要在撰写时绘制在位图支持的 Canvas 中。

如果我只是在 Canvas 的 DrawScope 中绘制缩略图,则可以正确绘制缩略图,但用户体验很差。当用户滚动 LazyVerticalGrid 时,每个缩略图都会自行绘制,因此会出现很多卡顿现象。

我原以为 Jetpack Compose 在需要时在后台线程中组合,但这一切似乎都发生在主线程上,导致严重的卡顿,即使在最新的手机上也是如此。

我可以通过使用 LaunchedEffect withContext(IO) 在另一个线程上绘制到 Canvas 的底层位图来解决卡顿问题。但问题是,Compose 不知道在绘制位图时重新组合 Canvas,所以我经常以半绘制的缩略图结束。

有没有一种方法可以在主线程之外完成工作,然后在完成工作后重新组合?

这是卡住的代码(为简洁起见进行了编辑),然后是在绘图完成后并不总是重新组合的非卡住版本:

   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())
       }
   }

非简陋但仍然不正确

   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())
       }
   }

【问题讨论】:

    标签: android android-jetpack-compose android-canvas


    【解决方案1】:

    最后,我使用了人们似乎用来强制 Jetpack Compose 根据命令重绘的常见“invalidate++”kludge。我认为它有一点代码味道,但它确实有效。

    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())
          }
       }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-12-21
      • 2022-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-26
      • 1970-01-01
      • 2020-03-12
      • 1970-01-01
      相关资源
      最近更新 更多