Merge remote-tracking branch 'origin/master' into gpeal/lottie-task
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 42d3e3c..c682a17 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
@@ -81,7 +81,10 @@
): LottieCompositionResult {
val context = LocalContext.current
val result by remember(spec) { mutableStateOf(LottieCompositionResultImpl()) }
- LaunchedEffect(spec) {
+ // Warm the task cache. We can start the parsing task before the LaunchedEffect gets dispatched and run.
+ // The LaunchedEffect task will join the task created inline here via LottieCompositionFactory's task cache.
+ remember(spec, cacheKey) { lottieTask(context, spec, cacheKey, isWarmingCache = true) }
+ LaunchedEffect(spec, cacheKey) {
var exception: Throwable? = null
var failedCount = 0
while (!result.isSuccess && (failedCount == 0 || onRetry(failedCount, exception!!))) {
@@ -115,7 +118,23 @@
fontFileExtension: String,
cacheKey: String?,
): LottieComposition {
- val task = when (spec) {
+ val task = requireNotNull(lottieTask(context, spec, cacheKey, isWarmingCache = false)) {
+ "Unable to create parsing task for $spec."
+ }
+
+ val composition = task.await()
+ loadImagesFromAssets(context, composition, imageAssetsFolder)
+ loadFontsFromAssets(context, composition, fontAssetsFolder, fontFileExtension)
+ return composition
+}
+
+private fun lottieTask(
+ context: Context,
+ spec: LottieCompositionSpec,
+ cacheKey: String?,
+ isWarmingCache: Boolean,
+): LottieTask<LottieComposition>? {
+ return when (spec) {
is LottieCompositionSpec.RawRes -> {
if (cacheKey == DefaultCacheKey) {
LottieCompositionFactory.fromRawRes(context, spec.resId)
@@ -131,16 +150,19 @@
}
}
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 })
+ if (isWarmingCache) {
+ // Warming the cache is done from the main thread so we can't
+ // create the FileInputStream needed in this path.
+ null
+ } else {
+ val fis = 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 -> {
@@ -155,11 +177,6 @@
LottieCompositionFactory.fromJsonString(spec.jsonString, jsonStringCacheKey)
}
}
-
- val composition = task.await()
- loadImagesFromAssets(context, composition, imageAssetsFolder)
- loadFontsFromAssets(context, composition, fontAssetsFolder, fontFileExtension)
- return composition
}
private suspend fun <T> LottieTask<T>.await(): T = suspendCancellableCoroutine { cont ->