aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Peal <gpeal@users.noreply.github.com>2019-11-30 14:47:35 -0800
committerGitHub <noreply@github.com>2019-11-30 14:47:35 -0800
commitee942249214dd6bb1540b746ca0b678a6382b5ee (patch)
tree15f355f7a61e4d2f32b1d5ccba34a7e7764599d1
parent8d676e1f08a99d18e1d09fa347435e3ff476c27c (diff)
downloadlottie-ee942249214dd6bb1540b746ca0b678a6382b5ee.tar.gz
Add the ability to set custom cache keys or set non cache key (#1450)
Fixes #1289
-rw-r--r--LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PlayerViewModel.kt6
-rw-r--r--lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java26
-rw-r--r--lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java115
-rw-r--r--lottie/src/main/res/values/attrs.xml1
4 files changed, 122 insertions, 26 deletions
diff --git a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PlayerViewModel.kt b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PlayerViewModel.kt
index dac6429d..46e414e9 100644
--- a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PlayerViewModel.kt
+++ b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PlayerViewModel.kt
@@ -40,9 +40,9 @@ class PlayerViewModel(
val url = args.url ?: args.animationData?.lottieLink
when {
- url != null -> LottieCompositionFactory.fromUrl(application, url)
+ url != null -> LottieCompositionFactory.fromUrl(application, url, null)
args.fileUri != null -> taskForUri(args.fileUri)
- args.asset != null -> LottieCompositionFactory.fromAsset(application, args.asset)
+ args.asset != null -> LottieCompositionFactory.fromAsset(application, args.asset, null)
else -> throw IllegalArgumentException("Don't know how to fetch animation for $args")
}
.addListener {
@@ -64,7 +64,7 @@ class PlayerViewModel(
return LottieTask { throw e }
}
- return LottieCompositionFactory.fromJsonInputStream(fis, uri.toString())
+ return LottieCompositionFactory.fromJsonInputStream(fis, null)
}
fun toggleRenderGraphVisible() = setState { copy(renderGraphVisible = !renderGraphVisible) }
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java b/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
index 82f4a647..ed780c1e 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
@@ -101,6 +101,7 @@ import static com.airbnb.lottie.RenderMode.HARDWARE;
private boolean wasAnimatingWhenNotShown = false;
private boolean wasAnimatingWhenDetached = false;
private boolean autoPlay = false;
+ private boolean cacheComposition = true;
private RenderMode renderMode = RenderMode.AUTOMATIC;
private Set<LottieOnCompositionLoadedListener> lottieOnCompositionLoadedListeners = new HashSet<>();
/**
@@ -134,6 +135,7 @@ import static com.airbnb.lottie.RenderMode.HARDWARE;
private void init(@Nullable AttributeSet attrs) {
TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.LottieAnimationView);
if (!isInEditMode()) {
+ cacheComposition = ta.getBoolean(R.styleable.LottieAnimationView_lottie_cacheComposition, true);
boolean hasRawRes = ta.hasValue(R.styleable.LottieAnimationView_lottie_rawRes);
boolean hasFileName = ta.hasValue(R.styleable.LottieAnimationView_lottie_fileName);
boolean hasUrl = ta.hasValue(R.styleable.LottieAnimationView_lottie_url);
@@ -349,19 +351,35 @@ import static com.airbnb.lottie.RenderMode.HARDWARE;
}
/**
+ * If set to true, all future compositions that are set will be cached so that they don't need to be parsed
+ * next time they are loaded. This won't apply to compositions that have already been loaded.
+ *
+ * Defaults to true.
+ *
+ * {@link R.attr#lottie_cacheComposition}
+ */
+ public void setCacheComposition(boolean cacheComposition) {
+ this.cacheComposition = cacheComposition;
+ }
+
+ /**
* Sets the animation from a file in the raw directory.
* This will load and deserialize the file asynchronously.
*/
public void setAnimation(@RawRes final int rawRes) {
this.animationResId = rawRes;
animationName = null;
- setCompositionTask(LottieCompositionFactory.fromRawRes(getContext(), rawRes));
+ LottieTask<LottieComposition> task = cacheComposition ?
+ LottieCompositionFactory.fromRawRes(getContext(), rawRes) : LottieCompositionFactory.fromRawRes(getContext(), rawRes, null);
+ setCompositionTask(task);
}
public void setAnimation(final String assetName) {
this.animationName = assetName;
animationResId = 0;
- setCompositionTask(LottieCompositionFactory.fromAsset(getContext(), assetName));
+ LottieTask<LottieComposition> task = cacheComposition ?
+ LottieCompositionFactory.fromAsset(getContext(), assetName) : LottieCompositionFactory.fromAsset(getContext(), assetName, null);
+ setCompositionTask(task);
}
/**
@@ -401,7 +419,9 @@ import static com.airbnb.lottie.RenderMode.HARDWARE;
* can be accessed immediately for subsequent requests. If the file does not parse to a composition, the temporary file will be deleted.
*/
public void setAnimationFromUrl(String url) {
- setCompositionTask(LottieCompositionFactory.fromUrl(getContext(), url));
+ LottieTask<LottieComposition> task = cacheComposition ?
+ LottieCompositionFactory.fromUrl(getContext(), url) : LottieCompositionFactory.fromUrl(getContext(), url, null);
+ setCompositionTask(task);
}
/**
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java b/lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java
index f2972796..a1d394fc 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java
@@ -65,10 +65,20 @@ public class LottieCompositionFactory {
* Fetch an animation from an http url. Once it is downloaded once, Lottie will cache the file to disk for
* future use. Because of this, you may call `fromUrl` ahead of time to warm the cache if you think you
* might need an animation in the future.
+ *
+ * To skip the cache, add null as a third parameter.
*/
public static LottieTask<LottieComposition> fromUrl(final Context context, final String url) {
- String urlCacheKey = "url_" + url;
- return cache(urlCacheKey, new Callable<LottieResult<LottieComposition>>() {
+ return fromUrl(context, url, "url_" + url);
+ }
+
+ /**
+ * Fetch an animation from an http url. Once it is downloaded once, Lottie will cache the file to disk for
+ * future use. Because of this, you may call `fromUrl` ahead of time to warm the cache if you think you
+ * might need an animation in the future.
+ */
+ public static LottieTask<LottieComposition> fromUrl(final Context context, final String url, @Nullable String cacheKey) {
+ return cache(cacheKey, new Callable<LottieResult<LottieComposition>>() {
@Override
public LottieResult<LottieComposition> call() {
return NetworkFetcher.fetchSync(context, url);
@@ -91,15 +101,31 @@ public class LottieCompositionFactory {
* The asset file name will be used as a cache key so future usages won't have to parse the json again.
* However, if your animation has images, you may package the json and images as a single flattened zip file in assets.
*
+ * To skip the cache, add null as a third parameter.
+ *
* @see #fromZipStream(ZipInputStream, String)
*/
public static LottieTask<LottieComposition> fromAsset(Context context, final String fileName) {
+ String cacheKey = "asset_" + fileName;
+ return fromAsset(context, fileName, cacheKey);
+ }
+
+ /**
+ * Parse an animation from src/main/assets. It is recommended to use {@link #fromRawRes(Context, int)} instead.
+ * The asset file name will be used as a cache key so future usages won't have to parse the json again.
+ * However, if your animation has images, you may package the json and images as a single flattened zip file in assets.
+ *
+ * Pass null as the cache key to skip the cache.
+ *
+ * @see #fromZipStream(ZipInputStream, String)
+ */
+ 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(fileName, new Callable<LottieResult<LottieComposition>>() {
+ return cache(cacheKey, new Callable<LottieResult<LottieComposition>>() {
@Override
public LottieResult<LottieComposition> call() {
- return fromAssetSync(appContext, fileName);
+ return fromAssetSync(appContext, fileName, cacheKey);
}
});
}
@@ -109,12 +135,28 @@ public class LottieCompositionFactory {
* The asset file name will be used as a cache key so future usages won't have to parse the json again.
* However, if your animation has images, you may package the json and images as a single flattened zip file in assets.
*
+ * To skip the cache, add null as a third parameter.
+ *
* @see #fromZipStreamSync(ZipInputStream, String)
*/
@WorkerThread
public static LottieResult<LottieComposition> fromAssetSync(Context context, String fileName) {
- try {
String cacheKey = "asset_" + fileName;
+ return fromAssetSync(context, fileName, cacheKey);
+ }
+
+ /**
+ * Parse an animation from src/main/assets. It is recommended to use {@link #fromRawRes(Context, int)} instead.
+ * The asset file name will be used as a cache key so future usages won't have to parse the json again.
+ * However, if your animation has images, you may package the json and images as a single flattened zip file in assets.
+ *
+ * Pass null as the cache key to skip the cache.
+ *
+ * @see #fromZipStreamSync(ZipInputStream, String)
+ */
+ @WorkerThread
+ public static LottieResult<LottieComposition> fromAssetSync(Context context, String fileName, @Nullable String cacheKey) {
+ try {
if (fileName.endsWith(".zip")) {
return fromZipStreamSync(new ZipInputStream(context.getAssets().open(fileName)), cacheKey);
}
@@ -131,12 +173,27 @@ public class LottieCompositionFactory {
* The resource id will be used as a cache key so future usages won't parse the json again.
* Note: to correctly load dark mode (-night) resources, make sure you pass Activity as a context (instead of e.g. the application context).
* The Activity won't be leaked.
+ *
+ * To skip the cache, add null as a third parameter.
*/
public static LottieTask<LottieComposition> fromRawRes(Context context, @RawRes final int rawRes) {
+ return fromRawRes(context, rawRes, rawResCacheKey(context, rawRes));
+ }
+
+ /**
+ * Parse an animation from raw/res. This is recommended over putting your animation in assets because
+ * it uses a hard reference to R.
+ * The resource id will be used as a cache key so future usages won't parse the json again.
+ * Note: to correctly load dark mode (-night) resources, make sure you pass Activity as a context (instead of e.g. the application context).
+ * The Activity won't be leaked.
+ *
+ * Pass null as the cache key to skip caching.
+ */
+ public static LottieTask<LottieComposition> fromRawRes(Context context, @RawRes final int rawRes, @Nullable String cacheKey) {
// Prevent accidentally leaking an Activity.
final WeakReference<Context> contextRef = new WeakReference<>(context);
final Context appContext = context.getApplicationContext();
- return cache(rawResCacheKey(context, rawRes), new Callable<LottieResult<LottieComposition>>() {
+ return cache(cacheKey, new Callable<LottieResult<LottieComposition>>() {
@Override
public LottieResult<LottieComposition> call() {
@Nullable Context originalContext = contextRef.get();
@@ -152,11 +209,27 @@ public class LottieCompositionFactory {
* The resource id will be used as a cache key so future usages won't parse the json again.
* Note: to correctly load dark mode (-night) resources, make sure you pass Activity as a context (instead of e.g. the application context).
* The Activity won't be leaked.
+ *
+ * To skip the cache, add null as a third parameter.
*/
@WorkerThread
public static LottieResult<LottieComposition> fromRawResSync(Context context, @RawRes int rawRes) {
+ return fromRawResSync(context, rawRes, rawResCacheKey(context, rawRes));
+ }
+
+ /**
+ * Parse an animation from raw/res. This is recommended over putting your animation in assets because
+ * it uses a hard reference to R.
+ * The resource id will be used as a cache key so future usages won't parse the json again.
+ * Note: to correctly load dark mode (-night) resources, make sure you pass Activity as a context (instead of e.g. the application context).
+ * The Activity won't be leaked.
+ *
+ * Pass null as the cache key to skip caching.
+ */
+ @WorkerThread
+ public static LottieResult<LottieComposition> fromRawResSync(Context context, @RawRes int rawRes, @Nullable String cacheKey) {
try {
- return fromJsonInputStreamSync(context.getResources().openRawResource(rawRes), rawResCacheKey(context, rawRes));
+ return fromJsonInputStreamSync(context.getResources().openRawResource(rawRes), cacheKey);
} catch (Resources.NotFoundException e) {
return new LottieResult<>(e);
}
@@ -399,19 +472,21 @@ public class LottieCompositionFactory {
}
LottieTask<LottieComposition> task = new LottieTask<>(callable);
- task.addListener(new LottieListener<LottieComposition>() {
- @Override
- public void onResult(LottieComposition result) {
- taskCache.remove(cacheKey);
- }
- });
- task.addFailureListener(new LottieListener<Throwable>() {
- @Override
- public void onResult(Throwable result) {
- taskCache.remove(cacheKey);
- }
- });
- taskCache.put(cacheKey, task);
+ if (cacheKey != null) {
+ task.addListener(new LottieListener<LottieComposition>() {
+ @Override
+ public void onResult(LottieComposition result) {
+ taskCache.remove(cacheKey);
+ }
+ });
+ task.addFailureListener(new LottieListener<Throwable>() {
+ @Override
+ public void onResult(Throwable result) {
+ taskCache.remove(cacheKey);
+ }
+ });
+ taskCache.put(cacheKey, task);
+ }
return task;
}
}
diff --git a/lottie/src/main/res/values/attrs.xml b/lottie/src/main/res/values/attrs.xml
index 5d51c4a1..41f4c7ae 100644
--- a/lottie/src/main/res/values/attrs.xml
+++ b/lottie/src/main/res/values/attrs.xml
@@ -18,6 +18,7 @@
<attr name="lottie_colorFilter" format="color" />
<attr name="lottie_scale" format="float" />
<attr name="lottie_speed" format="float" />
+ <attr name="lottie_cacheComposition" format="boolean" />
<!-- These values must be kept in sync with the RenderMode enum -->
<attr name="lottie_renderMode" format="enum">
<enum name="automatic" value="0" />