Skip to content

Commit

Permalink
Extract factories for Animatable classes (#152)
Browse files Browse the repository at this point in the history
In this pass I've converted BaseAnimatableValue and its subclasses.
Created a AnimatableValueParser with the common logic to all subclasses.
This change caused a "chicken and egg" problem where the AnimatableValueParser calls into Keyframe.Factory.parseKeyframes, which needs the respective instance of BaseAnimatableValue. This caused a circular dependency issue. I've resolved by moving AnimatableValue#valueFromObject() into a separate interface called AnimatableValue.Factory which contains only that method.
I think almost all the relevant classes have been refactored by now.
Part of #3
  • Loading branch information
felipecsl authored and gpeal committed Feb 23, 2017
1 parent 7d25209 commit 46904fc
Show file tree
Hide file tree
Showing 26 changed files with 335 additions and 166 deletions.
23 changes: 17 additions & 6 deletions lottie/src/main/java/com/airbnb/lottie/AnimatableColorValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

import org.json.JSONObject;

class AnimatableColorValue extends BaseAnimatableValue<Integer, Integer> {
AnimatableColorValue(JSONObject json, LottieComposition composition) {
super(json, composition, false);
}
import java.util.List;

@Override public Integer valueFromObject(Object object, float scale) {
return ColorFactory.newInstance(object);
class AnimatableColorValue extends BaseAnimatableValue<Integer, Integer> {
private AnimatableColorValue(List<Keyframe<Integer>> keyframes, LottieComposition composition,
Integer initialValue) {
super(keyframes, composition, initialValue);
}

@Override public KeyframeAnimation<Integer> createAnimation() {
Expand All @@ -21,4 +20,16 @@ class AnimatableColorValue extends BaseAnimatableValue<Integer, Integer> {
@Override public String toString() {
return "AnimatableColorValue{" + "initialValue=" + initialValue + '}';
}

static final class Factory {
private Factory() {
}

static AnimatableColorValue newInstance(JSONObject json, LottieComposition composition) {
AnimatableValueParser.Result<Integer> result = AnimatableValueParser
.newInstance(json, 1f, composition, ColorFactory.INSTANCE)
.parseJson();
return new AnimatableColorValue(result.keyframes, composition, result.initialValue);
}
}
}
53 changes: 40 additions & 13 deletions lottie/src/main/java/com/airbnb/lottie/AnimatableFloatValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,16 @@

import org.json.JSONObject;

class AnimatableFloatValue extends BaseAnimatableValue<Float, Float> {
AnimatableFloatValue(LottieComposition composition, Float initialValue) {
super(composition);
this.initialValue = initialValue;
}
import java.util.List;

AnimatableFloatValue(JSONObject json, LottieComposition composition) {
this(json, composition, true);
}

AnimatableFloatValue(JSONObject json, LottieComposition composition, boolean isDp) {
super(json, composition, isDp);
class AnimatableFloatValue extends BaseAnimatableValue<Float, Float> {
private AnimatableFloatValue(LottieComposition composition, Float initialValue) {
super(composition, initialValue);
}

@Override public Float valueFromObject(Object object, float scale) {
return JsonUtils.valueFromObject(object) * scale;
private AnimatableFloatValue(List<Keyframe<Float>> keyframes,
LottieComposition composition, Float initialValue) {
super(keyframes, composition, initialValue);
}

@Override public KeyframeAnimation<Float> createAnimation() {
Expand All @@ -31,4 +25,37 @@ class AnimatableFloatValue extends BaseAnimatableValue<Float, Float> {
public Float getInitialValue() {
return initialValue;
}

private static class ValueFactory implements AnimatableValue.Factory<Float> {
static final ValueFactory INSTANCE = new ValueFactory();

private ValueFactory() {
}

@Override public Float valueFromObject(Object object, float scale) {
return JsonUtils.valueFromObject(object) * scale;
}
}

static final class Factory {
private Factory() {
}

static AnimatableFloatValue newInstance(LottieComposition composition, Float initialValue) {
return new AnimatableFloatValue(composition, initialValue);
}

static AnimatableFloatValue newInstance(JSONObject json, LottieComposition composition) {
return newInstance(json, composition, true);
}

static AnimatableFloatValue newInstance(JSONObject json, LottieComposition composition,
boolean isDp) {
float scale = isDp ? composition.getScale() : 1f;
AnimatableValueParser.Result<Float> result = AnimatableValueParser
.newInstance(json, scale, composition, ValueFactory.INSTANCE)
.parseJson();
return new AnimatableFloatValue(result.keyframes, composition, result.initialValue);
}
}
}
64 changes: 46 additions & 18 deletions lottie/src/main/java/com/airbnb/lottie/AnimatableIntegerValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,16 @@

import org.json.JSONObject;

class AnimatableIntegerValue extends BaseAnimatableValue<Integer, Integer> {
AnimatableIntegerValue(LottieComposition composition, Integer initialValue) {
super(composition);
this.initialValue = initialValue;
}
import java.util.List;

AnimatableIntegerValue(JSONObject json, LottieComposition composition,
boolean isDp, boolean remap100To255) {
super(json, composition, isDp);
if (remap100To255) {
initialValue = initialValue * 255 / 100;
for (int i = 0; i < keyframes.size(); i++) {
Keyframe<Integer> keyframe = keyframes.get(i);
keyframe.startValue = keyframe.startValue * 255 / 100;
keyframe.endValue = keyframe.endValue * 255 / 100;
}
}
class AnimatableIntegerValue extends BaseAnimatableValue<Integer, Integer> {
private AnimatableIntegerValue(LottieComposition composition, Integer initialValue) {
super(composition, initialValue);
}

@Override public Integer valueFromObject(Object object, float scale) {
return Math.round(JsonUtils.valueFromObject(object) * scale);
private AnimatableIntegerValue(List<Keyframe<Integer>> keyframes, LottieComposition composition,
Integer initialValue) {
super(keyframes, composition, initialValue);
}

@Override public KeyframeAnimation<Integer> createAnimation() {
Expand All @@ -36,4 +25,43 @@ class AnimatableIntegerValue extends BaseAnimatableValue<Integer, Integer> {
public Integer getInitialValue() {
return initialValue;
}

static final class Factory {
private Factory() {
}

static AnimatableIntegerValue newInstance(LottieComposition composition, Integer initialValue) {
return new AnimatableIntegerValue(composition, initialValue);
}

static AnimatableIntegerValue newInstance(JSONObject json, LottieComposition composition,
boolean isDp, boolean remap100To255) {
float scale = isDp ? composition.getScale() : 1f;
AnimatableValueParser.Result<Integer> result = AnimatableValueParser
.newInstance(json, scale, composition, ValueFactory.INSTANCE)
.parseJson();
Integer initialValue = result.initialValue;
if (remap100To255 && result.initialValue != null) {
initialValue = result.initialValue * 255 / 100;
int size = result.keyframes.size();
for (int i = 0; i < size; i++) {
Keyframe<Integer> keyframe = result.keyframes.get(i);
keyframe.startValue = keyframe.startValue * 255 / 100;
keyframe.endValue = keyframe.endValue * 255 / 100;
}
}
return new AnimatableIntegerValue(result.keyframes, composition, initialValue);
}
}

private static class ValueFactory implements AnimatableValue.Factory<Integer> {
private static final ValueFactory INSTANCE = new ValueFactory();

private ValueFactory() {
}

@Override public Integer valueFromObject(Object object, float scale) {
return Math.round(JsonUtils.valueFromObject(object) * scale);
}
}
}
22 changes: 15 additions & 7 deletions lottie/src/main/java/com/airbnb/lottie/AnimatablePathValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ static IAnimatablePathValue createAnimatablePathOrSplitDimensionPath(
return new AnimatablePathValue(json.opt("k"), composition);
} else {
return new AnimatableSplitDimensionPathValue(
new AnimatableFloatValue(json.optJSONObject("x"), composition),
new AnimatableFloatValue(json.optJSONObject("y"), composition));
AnimatableFloatValue.Factory.newInstance(json.optJSONObject("x"), composition),
AnimatableFloatValue.Factory.newInstance(json.optJSONObject("y"), composition));
}
}

Expand All @@ -36,7 +36,8 @@ static IAnimatablePathValue createAnimatablePathOrSplitDimensionPath(
int length = jsonArray.length();
for (int i = 0; i < length; i++) {
JSONObject jsonKeyframe = jsonArray.optJSONObject(i);
PathKeyframe keyframe = PathKeyframe.Factory.newInstance(jsonKeyframe, composition, this);
PathKeyframe keyframe = PathKeyframe.Factory.newInstance(jsonKeyframe, composition,
ValueFactory.INSTANCE);
keyframes.add(keyframe);
}
Keyframe.setEndFrames(keyframes);
Expand All @@ -54,10 +55,6 @@ private boolean hasKeyframes(Object json) {
return firstObject instanceof JSONObject && ((JSONObject) firstObject).has("t");
}

@Override public PointF valueFromObject(Object object, float scale) {
return JsonUtils.pointFromJsonArray((JSONArray) object, scale);
}

@Override
public BaseKeyframeAnimation<?, PointF> createAnimation() {
if (!hasAnimation()) {
Expand All @@ -81,4 +78,15 @@ public PointF getInitialPoint() {
public String toString() {
return "initialPoint=" + initialPoint;
}

private static class ValueFactory implements AnimatableValue.Factory<PointF> {
private static final Factory<PointF> INSTANCE = new ValueFactory();

private ValueFactory() {
}

@Override public PointF valueFromObject(Object object, float scale) {
return JsonUtils.pointFromJsonArray((JSONArray) object, scale);
}
}
}
25 changes: 18 additions & 7 deletions lottie/src/main/java/com/airbnb/lottie/AnimatablePointValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,31 @@

import org.json.JSONObject;

class AnimatablePointValue extends BaseAnimatableValue<PointF, PointF> {
AnimatablePointValue(JSONObject pointValues, LottieComposition composition) {
super(pointValues, composition, true);
}
import java.util.List;

@Override public PointF valueFromObject(Object object, float scale) {
return PointFFactory.newInstance(object, scale);
class AnimatablePointValue extends BaseAnimatableValue<PointF, PointF> {
private AnimatablePointValue(List<Keyframe<PointF>> keyframes, LottieComposition composition,
PointF initialValue) {
super(keyframes, composition, initialValue);
}

@Override public KeyframeAnimation<PointF> createAnimation() {
if (!hasAnimation()) {
return new StaticKeyframeAnimation<>(initialValue);
} else {
return new PointKeyframeAnimation(keyframes);
}
}

return new PointKeyframeAnimation(keyframes);
static final class Factory {
private Factory() {
}

static AnimatablePointValue newInstance(JSONObject json, LottieComposition composition) {
AnimatableValueParser.Result<PointF> result = AnimatableValueParser
.newInstance(json, composition.getScale(), composition, PointFFactory.INSTANCE)
.parseJson();
return new AnimatablePointValue(result.keyframes, composition, result.initialValue);
}
}
}
34 changes: 25 additions & 9 deletions lottie/src/main/java/com/airbnb/lottie/AnimatableScaleValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,16 @@

import org.json.JSONObject;

class AnimatableScaleValue extends BaseAnimatableValue<ScaleXY, ScaleXY> {
AnimatableScaleValue(LottieComposition composition) {
super(composition);
initialValue = new ScaleXY();
}
import java.util.List;

AnimatableScaleValue(JSONObject scaleValues, LottieComposition composition, boolean isDp) {
super(scaleValues, composition, isDp);
class AnimatableScaleValue extends BaseAnimatableValue<ScaleXY, ScaleXY> {
private AnimatableScaleValue(LottieComposition composition) {
super(composition, new ScaleXY());
}

@Override public ScaleXY valueFromObject(Object object, float scale) {
return ScaleXY.Factory.newInstance(object, scale);
private AnimatableScaleValue(List<Keyframe<ScaleXY>> keyframes, LottieComposition composition,
ScaleXY initialValue) {
super(keyframes, composition, initialValue);
}

@Override public KeyframeAnimation<ScaleXY> createAnimation() {
Expand All @@ -23,4 +21,22 @@ class AnimatableScaleValue extends BaseAnimatableValue<ScaleXY, ScaleXY> {
return new ScaleKeyframeAnimation(keyframes);
}
}

static final class Factory {
private Factory() {
}

static AnimatableScaleValue newInstance(JSONObject json, LottieComposition
composition, boolean isDp) {
float scale = isDp ? composition.getScale() : 1f;
AnimatableValueParser.Result<ScaleXY> result = AnimatableValueParser
.newInstance(json, scale, composition, ScaleXY.Factory.INSTANCE)
.parseJson();
return new AnimatableScaleValue(result.keyframes, composition, result.initialValue);
}

static AnimatableScaleValue newInstance(LottieComposition composition) {
return new AnimatableScaleValue(composition);
}
}
}
27 changes: 19 additions & 8 deletions lottie/src/main/java/com/airbnb/lottie/AnimatableShapeValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,39 @@

import org.json.JSONObject;

import java.util.List;

class AnimatableShapeValue extends BaseAnimatableValue<ShapeData, Path> {
private final Path convertTypePath = new Path();

AnimatableShapeValue(JSONObject json, LottieComposition composition) {
super(json, composition, true);
}

@Override public ShapeData valueFromObject(Object object, float scale) {
return ShapeData.Factory.newInstance(object, scale);
private AnimatableShapeValue(List<Keyframe<ShapeData>> keyframes, LottieComposition composition,
ShapeData initialValue) {
super(keyframes, composition, initialValue);
}

@Override public BaseKeyframeAnimation<?, Path> createAnimation() {
if (!hasAnimation()) {
return new StaticKeyframeAnimation<>(convertType(initialValue));
} else {
return new ShapeKeyframeAnimation(keyframes);
}

return new ShapeKeyframeAnimation(keyframes);
}

@Override Path convertType(ShapeData shapeData) {
convertTypePath.reset();
MiscUtils.getPathFromData(shapeData, convertTypePath);
return convertTypePath;
}

static final class Factory {
private Factory() {
}

static AnimatableShapeValue newInstance(JSONObject json, LottieComposition composition) {
AnimatableValueParser.Result<ShapeData> result = AnimatableValueParser
.newInstance(json, composition.getScale(), composition, ShapeData.Factory.INSTANCE)
.parseJson();
return new AnimatableShapeValue(result.keyframes, composition, result.initialValue);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ class AnimatableSplitDimensionPathValue implements IAnimatablePathValue {
this.animatableYDimension = animatableYDimension;
}

@Override public PointF valueFromObject(Object object, float scale) {
return null;
}

@Override public KeyframeAnimation<PointF> createAnimation() {
return new SplitDimensionPathKeyframeAnimation(
animatableXDimension.createAnimation(), animatableYDimension.createAnimation());
Expand Down
Loading

0 comments on commit 46904fc

Please sign in to comment.