Fixed the stream was not closed when the lottie animation hit the cache (#2253)
This PR fixes the stream not closing when the lottie animation hits the cache.
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java b/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
index 09c8c02..4f451fb 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
@@ -470,6 +470,8 @@
* <p>
* This is particularly useful for animations loaded from the network. You can fetch the
* bodymovin json from the network and pass it directly here.
+ * <p>
+ * Auto-closes the stream.
*/
public void setAnimation(InputStream stream, @Nullable String cacheKey) {
setCompositionTask(LottieCompositionFactory.fromJsonInputStream(stream, cacheKey));
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java b/lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java
index 8532394..b74bcb1 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java
@@ -130,7 +130,7 @@
LottieCompositionCache.getInstance().put(cacheKey, result.getValue());
}
return result;
- });
+ }, null);
}
/**
@@ -184,7 +184,7 @@
public static LottieTask<LottieComposition> fromAsset(Context context, final String fileName, @Nullable final String cacheKey) {
// Prevent accidentally leaking an Activity.
final Context appContext = context.getApplicationContext();
- return cache(cacheKey, () -> fromAssetSync(appContext, fileName, cacheKey));
+ return cache(cacheKey, () -> fromAssetSync(appContext, fileName, cacheKey), null);
}
/**
@@ -254,7 +254,7 @@
@Nullable Context originalContext = contextRef.get();
Context context1 = originalContext != null ? originalContext : appContext;
return fromRawResSync(context1, rawRes, cacheKey);
- });
+ }, null);
}
/**
@@ -311,7 +311,7 @@
* @see #fromJsonInputStreamSync(InputStream, String, boolean)
*/
public static LottieTask<LottieComposition> fromJsonInputStream(final InputStream stream, @Nullable final String cacheKey) {
- return cache(cacheKey, () -> fromJsonInputStreamSync(stream, cacheKey));
+ return cache(cacheKey, () -> fromJsonInputStreamSync(stream, cacheKey), () -> closeQuietly(stream));
}
/**
@@ -343,7 +343,7 @@
return cache(cacheKey, () -> {
//noinspection deprecation
return fromJsonSync(json, cacheKey);
- });
+ }, null);
}
/**
@@ -361,7 +361,7 @@
* @see #fromJsonStringSync(String, String)
*/
public static LottieTask<LottieComposition> fromJsonString(final String json, @Nullable final String cacheKey) {
- return cache(cacheKey, () -> fromJsonStringSync(json, cacheKey));
+ return cache(cacheKey, () -> fromJsonStringSync(json, cacheKey), null);
}
/**
@@ -377,7 +377,7 @@
}
public static LottieTask<LottieComposition> fromJsonReader(final JsonReader reader, @Nullable final String cacheKey) {
- return cache(cacheKey, () -> fromJsonReaderSync(reader, cacheKey));
+ return cache(cacheKey, () -> fromJsonReaderSync(reader, cacheKey), () -> Utils.closeQuietly(reader));
}
@@ -417,7 +417,7 @@
* @see #fromZipStreamSync(Context, ZipInputStream, String)
*/
public static LottieTask<LottieComposition> fromZipStream(Context context, final ZipInputStream inputStream, @Nullable final String cacheKey) {
- return cache(cacheKey, () -> fromZipStreamSync(context, inputStream, cacheKey));
+ return cache(cacheKey, () -> fromZipStreamSync(context, inputStream, cacheKey), () -> closeQuietly(inputStream));
}
/**
@@ -604,17 +604,24 @@
* If not, create a new task for the callable.
* Then, add the new task to the task cache and set up listeners so it gets cleared when done.
*/
- private static LottieTask<LottieComposition> cache(
- @Nullable final String cacheKey, Callable<LottieResult<LottieComposition>> callable) {
+ private static LottieTask<LottieComposition> cache(@Nullable final String cacheKey, Callable<LottieResult<LottieComposition>> callable,
+ @Nullable Runnable onCached) {
+ LottieTask<LottieComposition> task = null;
final LottieComposition cachedComposition = cacheKey == null ? null : LottieCompositionCache.getInstance().get(cacheKey);
if (cachedComposition != null) {
- return new LottieTask<>(() -> new LottieResult<>(cachedComposition));
+ task = new LottieTask<>(() -> new LottieResult<>(cachedComposition));
}
if (cacheKey != null && taskCache.containsKey(cacheKey)) {
- return taskCache.get(cacheKey);
+ task = taskCache.get(cacheKey);
+ }
+ if (task != null) {
+ if (onCached != null) {
+ onCached.run();
+ }
+ return task;
}
- LottieTask<LottieComposition> task = new LottieTask<>(callable);
+ task = new LottieTask<>(callable);
if (cacheKey != null) {
AtomicBoolean resultAlreadyCalled = new AtomicBoolean(false);
task.addListener(result -> {