From 2163e1cc8d7b098e06093a10bcaaaa5a8180ef19 Mon Sep 17 00:00:00 2001 From: skydoves Date: Wed, 3 May 2023 17:04:35 +0900 Subject: [PATCH] Implement rememberTarget and clear target for Glide --- .../skydoves/landscapist/glide/GlideImage.kt | 13 ++-- .../landscapist/glide/RememberTarget.kt | 62 +++++++++++++++++++ landscapist/api/landscapist.api | 2 +- .../com/skydoves/landscapist/ImageLoad.kt | 14 +---- 4 files changed, 69 insertions(+), 22 deletions(-) create mode 100644 glide/src/main/kotlin/com/skydoves/landscapist/glide/RememberTarget.kt diff --git a/glide/src/main/kotlin/com/skydoves/landscapist/glide/GlideImage.kt b/glide/src/main/kotlin/com/skydoves/landscapist/glide/GlideImage.kt index e4075844..0ee5ebd1 100644 --- a/glide/src/main/kotlin/com/skydoves/landscapist/glide/GlideImage.kt +++ b/glide/src/main/kotlin/com/skydoves/landscapist/glide/GlideImage.kt @@ -26,13 +26,10 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.BoxWithConstraintsScope import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.painter.Painter -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.res.painterResource -import com.bumptech.glide.Glide import com.bumptech.glide.RequestBuilder import com.bumptech.glide.RequestManager import com.bumptech.glide.load.resource.gif.GifDrawable @@ -251,9 +248,10 @@ private fun GlideImage( content: @Composable BoxWithConstraintsScope.(imageState: ImageLoadState) -> Unit, ) { val requestManager = LocalGlideProvider.getGlideRequestManager() - val target = - remember(recomposeKey, imageOptions) { FlowCustomTarget(imageOptions = imageOptions) } - val context = LocalContext.current + val target = rememberTarget( + target = FlowCustomTarget(imageOptions = imageOptions), + imageOptions = imageOptions, + ) ImageLoad( recomposeKey = recomposeKey.value, @@ -281,9 +279,6 @@ private fun GlideImage( } }, imageOptions = imageOptions, - disposable = { - Glide.with(context).clear(target) - }, modifier = modifier, content = content, ) diff --git a/glide/src/main/kotlin/com/skydoves/landscapist/glide/RememberTarget.kt b/glide/src/main/kotlin/com/skydoves/landscapist/glide/RememberTarget.kt new file mode 100644 index 00000000..b17a3d3c --- /dev/null +++ b/glide/src/main/kotlin/com/skydoves/landscapist/glide/RememberTarget.kt @@ -0,0 +1,62 @@ +/* + * Designed and developed by 2020-2023 skydoves (Jaewoong Eum) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.skydoves.landscapist.glide + +import android.content.Context +import androidx.compose.runtime.Composable +import androidx.compose.runtime.RememberObserver +import androidx.compose.runtime.remember +import androidx.compose.ui.platform.LocalContext +import com.bumptech.glide.Glide +import com.skydoves.landscapist.ImageOptions + +/** + * Remember the given [FlowCustomTarget] in the current composition. + * + * The [FlowCustomTarget] will be cleared when the object leaves the composition. + * + * @param target the [FlowCustomTarget] to be remembered + * @param imageOptions the [ImageOptions] to be used a key. + */ +@Composable +internal fun rememberTarget( + target: FlowCustomTarget, + imageOptions: ImageOptions, +): FlowCustomTarget { + val context = LocalContext.current + return remember(target, imageOptions) { RememberableTarget(context, target) }.value +} + +internal class RememberableTarget( + private val context: Context, + private val target: FlowCustomTarget, +) : RememberObserver { + + internal val value: FlowCustomTarget + get() = target + + override fun onRemembered() { + // no-op + } + + override fun onAbandoned() { + Glide.with(context).clear(target) + } + + override fun onForgotten() { + Glide.with(context).clear(target) + } +} diff --git a/landscapist/api/landscapist.api b/landscapist/api/landscapist.api index 5901227d..b0cfa140 100644 --- a/landscapist/api/landscapist.api +++ b/landscapist/api/landscapist.api @@ -12,7 +12,7 @@ public final class com/skydoves/landscapist/DrawablePainterKt { } public final class com/skydoves/landscapist/ImageLoad { - public static final fun ImageLoad (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/Modifier;Lcom/skydoves/landscapist/ImageOptions;Lcom/skydoves/landscapist/constraints/Constrainable;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;II)V + public static final fun ImageLoad (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/Modifier;Lcom/skydoves/landscapist/ImageOptions;Lcom/skydoves/landscapist/constraints/Constrainable;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;II)V public static final fun getZeroConstraints ()J } diff --git a/landscapist/src/main/kotlin/com/skydoves/landscapist/ImageLoad.kt b/landscapist/src/main/kotlin/com/skydoves/landscapist/ImageLoad.kt index d2cd6ba7..009e7a70 100644 --- a/landscapist/src/main/kotlin/com/skydoves/landscapist/ImageLoad.kt +++ b/landscapist/src/main/kotlin/com/skydoves/landscapist/ImageLoad.kt @@ -21,12 +21,10 @@ package com.skydoves.landscapist import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.BoxWithConstraintsScope import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Constraints @@ -38,7 +36,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.emitAll import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.launch /** * A common image loading model for fetching an image asynchronously and @@ -56,7 +53,6 @@ public fun ImageLoad( modifier: Modifier = Modifier, imageOptions: ImageOptions, constrainable: Constrainable? = null, - disposable: (() -> Unit)? = null, content: @Composable BoxWithConstraintsScope.(imageState: ImageLoadState) -> Unit, ) { var state by remember(recomposeKey, imageOptions) { @@ -73,14 +69,8 @@ public fun ImageLoad( modifier = modifier.imageSemantics(imageOptions), propagateMinConstraints = true, ) { - val coroutineScope = rememberCoroutineScope() - DisposableEffect(key1 = recomposeKey, key2 = imageOptions) { - coroutineScope.launch { - constrainable?.setConstraints(constraints) - } - onDispose { - disposable?.invoke() - } + LaunchedEffect(key1 = recomposeKey, key2 = imageOptions) { + constrainable?.setConstraints(constraints) } content(state)