Only update listeners when animation changed (#1035)
diff --git a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PlayerFragment.kt b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PlayerFragment.kt
index cd7ad9f..bf47e6b 100644
--- a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PlayerFragment.kt
+++ b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PlayerFragment.kt
@@ -254,6 +254,11 @@
postInvalidate()
}
+ animationView.setOnClickListener {
+ // Click the animation view to re-render it for debugging purposes.
+ animationView.invalidate()
+ }
+
scaleSeekBar.setOnSeekBarChangeListener(OnSeekBarChangeListenerAdapter(
onProgressChanged = { _, progress, _ ->
val minScale = minScale()
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/BaseKeyframeAnimation.java b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/BaseKeyframeAnimation.java
index 0a1c475..3dd38df 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/BaseKeyframeAnimation.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/BaseKeyframeAnimation.java
@@ -1,14 +1,14 @@
package com.airbnb.lottie.animation.keyframe;
-import androidx.annotation.FloatRange;
-import androidx.annotation.Nullable;
-
-import com.airbnb.lottie.value.LottieValueCallback;
import com.airbnb.lottie.value.Keyframe;
+import com.airbnb.lottie.value.LottieValueCallback;
import java.util.ArrayList;
import java.util.List;
+import androidx.annotation.FloatRange;
+import androidx.annotation.Nullable;
+
/**
* @param <K> Keyframe type
* @param <A> Animation type
@@ -28,6 +28,10 @@
@Nullable private Keyframe<K> cachedKeyframe;
+ @Nullable private Keyframe<K> cachedGetValueKeyframe;
+ private float cachedGetValueProgress = -1f;
+ @Nullable private A cachedGetValue = null;
+
BaseKeyframeAnimation(List<? extends Keyframe<K>> keyframes) {
this.keyframes = keyframes;
}
@@ -41,6 +45,9 @@
}
public void setProgress(@FloatRange(from = 0f, to = 1f) float progress) {
+ // Must use hashCode() since the actual object instance will be returned
+ // from getValue() below with the new values.
+ int previousValue = valueCallback == null ? 0 : getValue().hashCode();
if (progress < getStartDelayProgress()) {
progress = getStartDelayProgress();
} else if (progress > getEndProgress()) {
@@ -51,8 +58,12 @@
return;
}
this.progress = progress;
+ // Just trigger a change but don't compute values if there is a value callback.
+ int newValue = valueCallback == null ? -1 : getValue().hashCode();
- notifyListeners();
+ if (previousValue != newValue) {
+ notifyListeners();
+ }
}
public void notifyListeners() {
@@ -122,7 +133,18 @@
}
public A getValue() {
- return getValue(getCurrentKeyframe(), getInterpolatedCurrentKeyframeProgress());
+ Keyframe<K> keyframe = getCurrentKeyframe();
+ float progress = getInterpolatedCurrentKeyframeProgress();
+ if (valueCallback == null && keyframe == cachedGetValueKeyframe && cachedGetValueProgress == progress) {
+ return cachedGetValue;
+ }
+
+ cachedGetValueKeyframe = keyframe;
+ cachedGetValueProgress = progress;
+ A value = getValue(keyframe, progress);
+ cachedGetValue = value;
+
+ return value;
}
public float getProgress() {