Skip to content

Commit bd02443

Browse files
committed
Recycle hardware bitmaps to release graphics memory sooner
1 parent 306a5c1 commit bd02443

2 files changed

Lines changed: 22 additions & 2 deletions

File tree

Readme.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
[![](https://img.shields.io/badge/ComposeBOM-2025.02.00-brightgreen)](https://developer.android.com/jetpack/compose/bom/bom)
44

55
🎉 News:
6+
- Memory footprint has been dramatically reduced on Android 10 and above, by leveraging [Hardware Bitmaps](https://bumptech.github.io/glide/doc/hardwarebitmaps.html).
7+
Software rendering is however still required when there's more than one layer.
68
- MapCompose Multiplatform is officially released: https://github.com/p-lr/MapComposeMP \
79
Works on iOS, MacOS, Windows, Linux, and Android.
810
- New path dash pattern api: ability to define a sequence made of dash, dot, and gap.
@@ -73,7 +75,7 @@ There's an example in the demo app.
7375

7476
Add this to your module's build.gradle
7577
```groovy
76-
implementation 'ovh.plrapps:mapcompose:2.15.0'
78+
implementation 'ovh.plrapps:mapcompose:2.16.0'
7779
```
7880

7981
Starting with v.2.4.1, the library is using the

mapcompose/src/main/java/ovh/plrapps/mapcompose/ui/state/TileCanvasState.kt

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ internal class TileCanvasState(
6060
private val lastVisible: VisibleTiles?
6161
get() = visibleStateFlow.value?.visibleTiles
6262

63+
private val recycleChannel = Channel<Tile>(Channel.UNLIMITED)
64+
6365
/**
6466
* So long as this debounced channel is offered a message, the lambda isn't called.
6567
*/
@@ -117,6 +119,14 @@ internal class TileCanvasState(
117119
scope.launch {
118120
consumeTiles(tilesOutput)
119121
}
122+
123+
scope.launch(Dispatchers.Main) {
124+
for (t in recycleChannel) {
125+
val b = t.bitmap
126+
t.bitmap = null
127+
b?.recycle()
128+
}
129+
}
120130
}
121131

122132
fun setLayers(layers: List<Layer>) {
@@ -409,12 +419,20 @@ internal class TileCanvasState(
409419
}
410420

411421
/**
412-
* After a [Tile] is no longer visible, recycle its Bitmap and Paint if possible, for later use.
422+
* After a [Tile] is no longer visible, depending on the bitmap mutability:
423+
* - If the Bitmap is mutable, put it into the pool for later use.
424+
* - If the bitmap isn't mutable, we don't use bitmap pooling. That means the associated graphic
425+
* memory can be reclaimed asap.
426+
* The Compose framework draws tiles on the main thread and checks whether or not [Tile.bitmap]
427+
* is null. So, prior to calling recycle() we set [Tile.bitmap] to null on the main thread. This
428+
* is done inside the coroutine which consumes [recycleChannel].
413429
*/
414430
private fun Tile.recycle() {
415431
val b = bitmap ?: return
416432
if (b.isMutable) {
417433
bitmapPool.put(b)
434+
} else {
435+
recycleChannel.trySend(this)
418436
}
419437
alpha = 0f
420438
}

0 commit comments

Comments
 (0)