0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Androidで Google Mapsのカスタムマーカーで bitmap.recycle() したらクラッシュした

0
Posted at

クラッシュが起きた時

Jetpack Compose + Google Maps でルート地図にスタート・ゴールのカスタムマーカーを実装していました。マーカーのアイコンは Bitmap に Canvas で描画し BitmapDescriptorFactory.fromBitmap() に渡す方式です。

  @Composable  
  private fun rememberStartMarkerIcon(): BitmapDescriptor? {
      val density = LocalDensity.current                                                                                                                                                       
      return remember(density) {
          val bitmap = Bitmap.createBitmap(widthPx, heightPx, Bitmap.Config.ARGB_8888)                                                                                                         
          val canvas = android.graphics.Canvas(bitmap)                          
          // Canvas に旗を描画
          canvas.drawPath(flagPath, flagPaint) 
          canvas.drawLine(poleX, 0f, poleX, heightPx.toFloat(), polePaint)               
          BitmapDescriptorFactory.fromBitmap(bitmap).also { bitmap.recycle() }                                                                                                                 
      }    
  }   

描画が終わった Bitmap はもう不要だと思い、also { bitmap.recycle() } で即解放しました。

これで動作確認のためにマップ画面を開いた瞬間にクラッシュしました。

  Fatal Exception: java.lang.RuntimeException
  Canvas: trying to use a recycled bitmap android.graphics.Bitmap@XXXXXXXX    

recycle() の行は疑わなかったため、原因特定に時間がかかりましたが、いろいろ調べた結果原因は、fromBitmap() は Bitmap をコピーしないという事でした。
BitmapDescriptorFactory.fromBitmap(bitmap) は渡した Bitmap の参照を内部に保持するだけで、その場でピクセルデータをコピーするわけではありません。実際にピクセルデータが読まれるのは、Google Maps がマーカーを画面に描画するときです。
recycle() の直後には落ちず、マップ初回描画時に落ちるので一見原因が見えにくいのが厄介でした。

解決法

解決しるのは簡単で、recycle() を消すだけ
具体的には、

BitmapDescriptorFactory.fromBitmap(bitmap).also { bitmap.recycle() } 

  BitmapDescriptorFactory.fromBitmap(bitmap)              

変更したらクラッシュしなくなりました。

理由は、 remember ブロック内であれば、マーカーが不要になると参照が切れて自動で解放されるそうです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?