Browse Source

Components. AnimatedImage. Fix 'load' function. (#2043)

Passed to 'load' lambda can change every recomposition (it depends on variables which are captured inside it)
pull/2047/head
Igor Demin 3 years ago committed by GitHub
parent
commit
4ff361bd62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 27
      components/AnimatedImage/demo/src/jvmMain/kotlin/org/jetbrains/compose/animatedimage/demo/Main.kt
  2. 38
      components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/LoadState.kt

27
components/AnimatedImage/demo/src/jvmMain/kotlin/org/jetbrains/compose/animatedimage/demo/Main.kt

@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.material.CircularProgressIndicator import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -16,16 +17,14 @@ import org.jetbrains.compose.resources.LoadState
import org.jetbrains.compose.resources.load import org.jetbrains.compose.resources.load
import org.jetbrains.compose.resources.loadOrNull import org.jetbrains.compose.resources.loadOrNull
fun main() = singleWindowApplication { private val url =
val url = "https://raw.githubusercontent.com/JetBrains/skija/ccf303ebcf926e5ef000fc42d1a6b5b7f1e0b2b5/examples/scenes/images/codecs/animated.gif"
"https://raw.githubusercontent.com/JetBrains/skija/ccf303ebcf926e5ef000fc42d1a6b5b7f1e0b2b5/examples/scenes/images/codecs/animated.gif"
// Load an image async
val animatedImage =
load { loadAnimatedImage(url) } // use "load { loadResourceAnimatedImage(url) }" for resources
fun main() = singleWindowApplication {
Column { Column {
when (animatedImage) { // Load an image async
// use "load { loadResourceAnimatedImage(url) }" for resources
when (val animatedImage = load { loadAnimatedImage(url) }) {
is LoadState.Success -> Image( is LoadState.Success -> Image(
bitmap = animatedImage.value.animate(), bitmap = animatedImage.value.animate(),
contentDescription = null, contentDescription = null,
@ -34,12 +33,10 @@ fun main() = singleWindowApplication {
is LoadState.Error -> Text("Error!") is LoadState.Error -> Text("Error!")
} }
Column { Image(
Image( loadOrNull { loadAnimatedImage(url) }?.animate() ?: ImageBitmap.Blank,
loadOrNull { loadAnimatedImage(url) }?.animate() ?: ImageBitmap.Blank, contentDescription = null,
contentDescription = null, Modifier.size(100.dp)
Modifier.size(100.dp) )
)
}
} }
} }

38
components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/LoadState.kt

@ -15,8 +15,38 @@ sealed class LoadState<T> {
@Composable @Composable
fun <T> load(load: suspend () -> T): LoadState<T> { fun <T> load(load: suspend () -> T): LoadState<T> {
var state: LoadState<T> by remember(load) { mutableStateOf(LoadState.Loading()) } return load(Unit, load)
LaunchedEffect(load) { }
@Composable
fun <T: Any> loadOrNull(load: suspend () -> T): T? {
return loadOrNull(Unit, load)
}
@Composable
fun <T> load(key1: Any?, load: suspend () -> T): LoadState<T> {
return load(key1, Unit, load)
}
@Composable
fun <T: Any> loadOrNull(key1: Any?, load: suspend () -> T): T? {
return loadOrNull(key1, Unit, load)
}
@Composable
fun <T> load(key1: Any?, key2: Any?, load: suspend () -> T): LoadState<T> {
return load(key1, key2, Unit, load)
}
@Composable
fun <T: Any> loadOrNull(key1: Any?, key2: Any?, load: suspend () -> T): T? {
return loadOrNull(key1, key2, Unit, load)
}
@Composable
fun <T> load(key1: Any?, key2: Any?, key3: Any?, load: suspend () -> T): LoadState<T> {
var state: LoadState<T> by remember(key1, key2, key3) { mutableStateOf(LoadState.Loading()) }
LaunchedEffect(key1, key2, key3) {
state = try { state = try {
LoadState.Success(load()) LoadState.Success(load())
} catch (e: Exception) { } catch (e: Exception) {
@ -27,7 +57,7 @@ fun <T> load(load: suspend () -> T): LoadState<T> {
} }
@Composable @Composable
fun <T: Any> loadOrNull(load: suspend () -> T): T? { fun <T: Any> loadOrNull(key1: Any?, key2: Any?, key3: Any?, load: suspend () -> T): T? {
val state = load(load) val state = load(key1, key2, key3, load)
return (state as? LoadState.Success<T>)?.value return (state as? LoadState.Success<T>)?.value
} }
Loading…
Cancel
Save