Revert "[Compose] Parse LottieComposition synchronously instead of using LottieTask" (#1890)
Reverts #1888
This was not a good solution. It lost task joining so requesting the same animation multiples would parse the animation multiple times.
diff --git a/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieCompositionSpec.kt b/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieCompositionSpec.kt
index ba38a5b..9444a5b 100644
--- a/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieCompositionSpec.kt
+++ b/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieCompositionSpec.kt
@@ -1,7 +1,5 @@
package com.airbnb.lottie.compose
-import com.airbnb.lottie.LottieComposition
-
/**
* Specification for a [com.airbnb.lottie.LottieComposition]. Each subclass represents a different source.
* A [com.airbnb.lottie.LottieComposition] is the stateless parsed version of a Lottie json file and is
@@ -43,9 +41,4 @@
* Load an animation from its json string.
*/
inline class JsonString(val jsonString: String) : LottieCompositionSpec
-
- /**
- * Load an animation from a custom factory. This will be called on an IO thread pool.
- */
- inline class Custom(val factory: () -> LottieComposition) : LottieCompositionSpec
}
diff --git a/lottie-compose/src/main/java/com/airbnb/lottie/compose/rememberLottieComposition.kt b/lottie-compose/src/main/java/com/airbnb/lottie/compose/rememberLottieComposition.kt
index f4f4187..42d3e3c 100644
--- a/lottie-compose/src/main/java/com/airbnb/lottie/compose/rememberLottieComposition.kt
+++ b/lottie-compose/src/main/java/com/airbnb/lottie/compose/rememberLottieComposition.kt
@@ -13,15 +13,18 @@
import com.airbnb.lottie.LottieComposition
import com.airbnb.lottie.LottieCompositionFactory
import com.airbnb.lottie.LottieImageAsset
-import com.airbnb.lottie.LottieResult
+import com.airbnb.lottie.LottieTask
import com.airbnb.lottie.model.Font
import com.airbnb.lottie.utils.Logger
import com.airbnb.lottie.utils.Utils
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import java.io.FileInputStream
import java.io.IOException
import java.util.zip.ZipInputStream
+import kotlin.coroutines.resume
+import kotlin.coroutines.resumeWithException
/**
* Use this with [rememberLottieComposition#cacheKey]'s cacheKey parameter to generate a default
@@ -78,7 +81,6 @@
): LottieCompositionResult {
val context = LocalContext.current
val result by remember(spec) { mutableStateOf(LottieCompositionResultImpl()) }
-
LaunchedEffect(spec) {
var exception: Throwable? = null
var failedCount = 0
@@ -113,63 +115,58 @@
fontFileExtension: String,
cacheKey: String?,
): LottieComposition {
- val result = parseCompositionSync(context, spec, cacheKey)
- result.exception?.let { throw it }
+ val task = when (spec) {
+ is LottieCompositionSpec.RawRes -> {
+ if (cacheKey == DefaultCacheKey) {
+ LottieCompositionFactory.fromRawRes(context, spec.resId)
+ } else {
+ LottieCompositionFactory.fromRawRes(context, spec.resId, cacheKey)
+ }
+ }
+ is LottieCompositionSpec.Url -> {
+ if (cacheKey == DefaultCacheKey) {
+ LottieCompositionFactory.fromUrl(context, spec.url)
+ } else {
+ LottieCompositionFactory.fromUrl(context, spec.url, cacheKey)
+ }
+ }
+ is LottieCompositionSpec.File -> {
+ val fis = withContext(Dispatchers.IO) {
+ @Suppress("BlockingMethodInNonBlockingContext")
+ FileInputStream(spec.fileName)
+ }
+ when {
+ spec.fileName.endsWith("zip") -> LottieCompositionFactory.fromZipStream(
+ ZipInputStream(fis),
+ spec.fileName.takeIf { cacheKey != null },
+ )
+ else -> LottieCompositionFactory.fromJsonInputStream(fis, spec.fileName.takeIf { cacheKey != null })
+ }
+ }
+ is LottieCompositionSpec.Asset -> {
+ if (cacheKey == DefaultCacheKey) {
+ LottieCompositionFactory.fromAsset(context, spec.assetName)
+ } else {
+ LottieCompositionFactory.fromAsset(context, spec.assetName, null)
+ }
+ }
+ is LottieCompositionSpec.JsonString -> {
+ val jsonStringCacheKey = if (cacheKey == DefaultCacheKey) spec.jsonString.hashCode().toString() else cacheKey
+ LottieCompositionFactory.fromJsonString(spec.jsonString, jsonStringCacheKey)
+ }
+ }
- val composition = result.value!!
+ val composition = task.await()
loadImagesFromAssets(context, composition, imageAssetsFolder)
loadFontsFromAssets(context, composition, fontAssetsFolder, fontFileExtension)
return composition
}
-private fun parseCompositionSync(
- context: Context,
- spec: LottieCompositionSpec,
- cacheKey: String?,
-): LottieResult<LottieComposition> {
- return when (spec) {
- is LottieCompositionSpec.RawRes -> {
- if (cacheKey == DefaultCacheKey) {
- LottieCompositionFactory.fromRawResSync(context, spec.resId)
- } else {
- LottieCompositionFactory.fromRawResSync(context, spec.resId, cacheKey)
- }
- }
- is LottieCompositionSpec.Url -> {
- if (cacheKey == DefaultCacheKey) {
- LottieCompositionFactory.fromUrlSync(context, spec.url)
- } else {
- LottieCompositionFactory.fromUrlSync(context, spec.url, cacheKey)
- }
- }
- is LottieCompositionSpec.File -> {
- val fis = FileInputStream(spec.fileName)
- when {
- spec.fileName.endsWith("zip") -> LottieCompositionFactory.fromZipStreamSync(
- ZipInputStream(fis),
- spec.fileName.takeIf { cacheKey != null },
- )
- else -> LottieCompositionFactory.fromJsonInputStreamSync(fis, spec.fileName.takeIf { cacheKey != null })
- }
- }
- is LottieCompositionSpec.Asset -> {
- if (cacheKey == DefaultCacheKey) {
- LottieCompositionFactory.fromAssetSync(context, spec.assetName)
- } else {
- LottieCompositionFactory.fromAssetSync(context, spec.assetName, null)
- }
- }
- is LottieCompositionSpec.JsonString -> {
- val jsonStringCacheKey = if (cacheKey == DefaultCacheKey) spec.jsonString.hashCode().toString() else cacheKey
- LottieCompositionFactory.fromJsonStringSync(spec.jsonString, jsonStringCacheKey)
- }
- is LottieCompositionSpec.Custom -> {
- try {
- LottieResult(spec.factory())
- } catch (e: Throwable) {
- LottieResult<LottieComposition>(e)
- }
- }
+private suspend fun <T> LottieTask<T>.await(): T = suspendCancellableCoroutine { cont ->
+ addListener { c ->
+ if (!cont.isCompleted) cont.resume(c)
+ }.addFailureListener { e ->
+ if (!cont.isCompleted) cont.resumeWithException(e)
}
}