@SuppressWarnings("unchecked")
  @Override
  public <T> void addValueCallback(T property, @Nullable LottieValueCallback<T> callback) {
    super.addValueCallback(property, callback);
    if (property == LottieProperty.COLOR) {
      if (colorCallbackAnimation != null) {
        removeAnimation(colorCallbackAnimation);
      }

      if (callback == null) {
        colorCallbackAnimation = null;
      } else {
        colorCallbackAnimation = new ValueCallbackKeyframeAnimation<>((LottieValueCallback<Integer>) callback);
        colorCallbackAnimation.addUpdateListener(this);
        addAnimation(colorCallbackAnimation);
      }
    } else if (property == LottieProperty.STROKE_COLOR) {
      if (strokeColorCallbackAnimation != null) {
        removeAnimation(strokeColorCallbackAnimation);
      }

      if (callback == null) {
        strokeColorCallbackAnimation = null;
      } else {
        strokeColorCallbackAnimation = new ValueCallbackKeyframeAnimation<>((LottieValueCallback<Integer>) callback);
        strokeColorCallbackAnimation.addUpdateListener(this);
        addAnimation(strokeColorCallbackAnimation);
      }
    } else if (property == LottieProperty.STROKE_WIDTH) {
      if (strokeWidthCallbackAnimation != null) {
        removeAnimation(strokeWidthCallbackAnimation);
      }

      if (callback == null) {
        strokeWidthCallbackAnimation = null;
      } else {
        strokeWidthCallbackAnimation = new ValueCallbackKeyframeAnimation<>((LottieValueCallback<Float>) callback);
        strokeWidthCallbackAnimation.addUpdateListener(this);
        addAnimation(strokeWidthCallbackAnimation);
      }
    } else if (property == LottieProperty.TEXT_TRACKING) {
      if (trackingCallbackAnimation != null) {
        removeAnimation(trackingCallbackAnimation);
      }

      if (callback == null) {
        trackingCallbackAnimation = null;
      } else {
        trackingCallbackAnimation = new ValueCallbackKeyframeAnimation<>((LottieValueCallback<Float>) callback);
        trackingCallbackAnimation.addUpdateListener(this);
        addAnimation(trackingCallbackAnimation);
      }
    } else if (property == LottieProperty.TEXT_SIZE) {
      if (textSizeCallbackAnimation != null) {
        removeAnimation(textSizeCallbackAnimation);
      }

      if (callback == null) {
        textSizeCallbackAnimation = null;
      } else {
        textSizeCallbackAnimation = new ValueCallbackKeyframeAnimation<>((LottieValueCallback<Float>) callback);
        textSizeCallbackAnimation.addUpdateListener(this);
        addAnimation(textSizeCallbackAnimation);
      }
    } else if (property == LottieProperty.TYPEFACE) {
      if (typefaceCallbackAnimation != null) {
        removeAnimation(typefaceCallbackAnimation);
      }

      if (callback == null) {
        typefaceCallbackAnimation = null;
      } else {
        typefaceCallbackAnimation = new ValueCallbackKeyframeAnimation<>((LottieValueCallback<Typeface>) callback);
        typefaceCallbackAnimation.addUpdateListener(this);
        addAnimation(typefaceCallbackAnimation);
      }
    } else if (property == LottieProperty.TEXT) {
      textAnimation.setStringValueCallback((LottieValueCallback<String>) callback);
    }
  }
Elements are reused and not deleted to save allocations.
lottie/src/main/java/com/airbnb/lottie/model/layer/TextLayer.java