Skip to content

Commit aab8b93

Browse files
copy bitmap on background thread
1 parent 69fc9bc commit aab8b93

File tree

3 files changed

+26
-24
lines changed

3 files changed

+26
-24
lines changed

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/BackgroundImageDrawable.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,9 @@ internal class BackgroundImageDrawable(
137137
// So we draw in reverse (last drawn in canvas appears closest)
138138
for (index in layers.indices.reversed()) {
139139
val backgroundImageLayer = layers[index]
140-
val size = backgroundSize?.let { it.getOrNull(index % it.size) }
141-
val repeat = backgroundRepeat?.let { it.getOrNull(index % it.size) }
142-
val position = backgroundPosition?.let { it.getOrNull(index % it.size) }
140+
val size = backgroundSize?.takeIf { it.isNotEmpty() }?.let { it[index % it.size] }
141+
val repeat = backgroundRepeat?.takeIf { it.isNotEmpty() }?.let { it[index % it.size] }
142+
val position = backgroundPosition?.takeIf { it.isNotEmpty() }?.let { it[index % it.size] }
143143

144144
val urlBitmap: Bitmap?
145145
val (intrinsicWidth, intrinsicHeight) = when (backgroundImageLayer) {
@@ -148,7 +148,7 @@ internal class BackgroundImageDrawable(
148148
backgroundPositioningArea.width() to backgroundPositioningArea.height()
149149
}
150150
is BackgroundImageLayer.URLImageLayer -> {
151-
val bitmap = backgroundImageLayer.loadedBitmap
151+
val bitmap = urlImageLoader.loadedBitmapForUri(backgroundImageLayer.uri)
152152
if (bitmap == null) {
153153
continue
154154
}
@@ -443,12 +443,12 @@ internal class BackgroundImageDrawable(
443443
}
444444

445445
private fun loadUrlImages(layers: List<BackgroundImageLayer>?) {
446-
val urlLayers = layers?.filterIsInstance<BackgroundImageLayer.URLImageLayer>()
447-
if (urlLayers.isNullOrEmpty()) {
446+
val uris = layers?.filterIsInstance<BackgroundImageLayer.URLImageLayer>()?.map { it.uri }
447+
if (uris.isNullOrEmpty()) {
448448
urlImageLoader.cancelAllRequests()
449449
return
450450
}
451451

452-
urlImageLoader.loadImages(urlLayers) { invalidateSelf() }
452+
urlImageLoader.loadImages(uris) { invalidateSelf() }
453453
}
454454
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/BackgroundImageURLLoader.kt

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,66 +9,70 @@ package com.facebook.react.uimanager.drawable
99

1010
import android.graphics.Bitmap
1111
import android.net.Uri
12-
import com.facebook.common.executors.UiThreadImmediateExecutorService
12+
import com.facebook.common.executors.CallerThreadExecutor
1313
import com.facebook.common.logging.FLog
1414
import com.facebook.common.references.CloseableReference
1515
import com.facebook.datasource.DataSource
1616
import com.facebook.drawee.backends.pipeline.Fresco
1717
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
1818
import com.facebook.imagepipeline.image.CloseableImage
1919
import com.facebook.imagepipeline.request.ImageRequestBuilder
20-
import com.facebook.react.uimanager.style.BackgroundImageLayer
20+
import com.facebook.react.bridge.UiThreadUtil
21+
import java.util.concurrent.ConcurrentHashMap
2122

2223
public class BackgroundImageURLLoader {
2324
private companion object {
2425
private const val TAG = "BackgroundImageURLLoader"
2526
}
2627

2728
private val pendingRequests = mutableMapOf<String, DataSource<CloseableReference<CloseableImage>>>()
29+
private val loadedBitmaps = ConcurrentHashMap<String, Bitmap>()
2830
private var onComplete: (() -> Unit)? = null
2931

3032
public fun loadImages(
31-
layers: List<BackgroundImageLayer.URLImageLayer>,
33+
uris: List<String>,
3234
onComplete: () -> Unit
3335
) {
3436
cancelAllRequests()
3537

36-
if (layers.isEmpty()) {
38+
if (uris.isEmpty()) {
3739
onComplete()
3840
return
3941
}
4042

4143
this.onComplete = onComplete
42-
for (layer in layers) {
43-
val imageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(layer.uri)).build()
44+
for (uri in uris) {
45+
val imageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(uri)).build()
4446
val imagePipeline = Fresco.getImagePipeline()
4547
val dataSource = imagePipeline.fetchDecodedImage(imageRequest, null)
4648

47-
pendingRequests[layer.uri] = dataSource
49+
pendingRequests[uri] = dataSource
4850

4951
dataSource.subscribe(
5052
object : BaseBitmapDataSubscriber() {
5153
override fun onNewResultImpl(bitmap: Bitmap?) {
5254
if (bitmap != null) {
53-
layer.loadedBitmap = bitmap.copy(bitmap.config ?: Bitmap.Config.ARGB_8888, false)
55+
loadedBitmaps[uri] = bitmap.copy(bitmap.config ?: Bitmap.Config.ARGB_8888, false)
5456
}
55-
onRequestComplete(layer.uri)
57+
onRequestComplete(uri)
5658
}
5759

5860
override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage>>) {
59-
FLog.w(TAG, "Failed to load background image: ${layer.uri}-${dataSource.failureCause}")
60-
onRequestComplete(layer.uri)
61+
FLog.w(TAG, "Failed to load background image: $uri-${dataSource.failureCause}")
62+
onRequestComplete(uri)
6163
}
6264
},
63-
UiThreadImmediateExecutorService.getInstance()
65+
CallerThreadExecutor.getInstance()
6466
)
6567
}
6668
}
6769

70+
public fun loadedBitmapForUri(uri: String): Bitmap? = loadedBitmaps[uri]
71+
6872
private fun onRequestComplete(uri: String) {
6973
pendingRequests.remove(uri)
7074
if (pendingRequests.isEmpty()) {
71-
onComplete?.invoke()
75+
UiThreadUtil.runOnUiThread { onComplete?.invoke() }
7276
}
7377
}
7478

@@ -77,6 +81,7 @@ public class BackgroundImageURLLoader {
7781
dataSource.close()
7882
}
7983
pendingRequests.clear()
84+
loadedBitmaps.clear()
8085
onComplete = null
8186
}
8287
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/BackgroundImageLayer.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
package com.facebook.react.uimanager.style
99

1010
import android.content.Context
11-
import android.graphics.Bitmap
1211
import android.graphics.Shader
1312
import com.facebook.react.bridge.ReadableMap
1413
import com.facebook.react.bridge.ReadableType
@@ -18,9 +17,7 @@ public sealed class BackgroundImageLayer {
1817
public fun getShader(width: Float, height: Float): Shader = gradient.getShader(width, height)
1918
}
2019

21-
public class URLImageLayer(public val uri: String) : BackgroundImageLayer() {
22-
public var loadedBitmap: Bitmap? = null
23-
}
20+
public class URLImageLayer(public val uri: String) : BackgroundImageLayer()
2421

2522
public companion object {
2623
public fun parse(backgroundImageMap: ReadableMap?, context: Context): BackgroundImageLayer? {

0 commit comments

Comments
 (0)