O animador de objeto não remove o ouvinte de atualização android

Bom dia. Eu tenho um cenário em que esse animador de objeto meio normal continua disparando repetidamente, causando heap crescer e, é claro, problemas de falta de memória em algum momento. Eu criei um método estático para animação de arco-íris como esta.

  public static ObjectAnimator startRainbowAnimation(Context context,
                                                   String textToShow,
                                                   final TextView textViewToAttach) {
    AnimatedColorSpan span = new AnimatedColorSpan(context);
    final SpannableString spannableString = new SpannableString(textToShow);
    String substring = textToShow;
    int start = textToShow.indexOf(substring);
    int end = start + substring.length();
    spannableString.setSpan(span, start, end, 0);

    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(
            span, ANIMATED_COLOR_SPAN_FLOAT_PROPERTY, 0, 100);
    objectAnimator.setEvaluator(new FloatEvaluator());
    objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {
            System.gc();
            Log.d("Fafasfasfas", "onAnimationUpdate: inside true");
            textViewToAttach.setText(spannableString);
        }
    });
    objectAnimator.setInterpolator(new LinearInterpolator());
    objectAnimator.setDuration(DURATION);
    objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
    objectAnimator.start();
    return objectAnimator;
}

private static final Property<AnimatedColorSpan, Float> ANIMATED_COLOR_SPAN_FLOAT_PROPERTY
        = new Property<AnimatedColorSpan, Float>(Float.class, "ANIMATED_COLOR_SPAN_FLOAT_PROPERTY") {
    @Override
    public void set(AnimatedColorSpan span, Float value) {
        span.setTranslateXPercentage(value);
    }

    @Override
    public Float get(AnimatedColorSpan span) {
        return span.getTranslateXPercentage();
    }
};

Estou chamando esse método assim dentro de um adaptador de exibição de reciclador

 @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        ChatModel chatModel = chatModelList.get(position);

        System.gc();

        String messageBody = chatModel.getMessage().replaceAll("userid=" + chatModel.getUserId() + ":" + Constants.TYPE_MESSAGE_ATTACHMENT, "").replaceAll("userid=" + chatModel.getOpponentId() + ":" + Constants.TYPE_MESSAGE_ATTACHMENT, "");
        holder.message.setText(messageBody);
         if (showAsRainbow) {
                if (holder.message.getTag() == null) {
                    objectAnimator = RainbowAnimation.startRainbowAnimation(mContext, messageBody, holder.message);
                    holder.message.setTag(ANIMATED);
                }
            } else {
                objectAnimator.removeAllUpdateListeners();
                objectAnimator.removeAllListeners();
                objectAnimator.end();
                objectAnimator.cancel();
                holder.message.setTag(null);
            }

        LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) holder.chatViewBubble.getLayoutParams();
        LinearLayout.LayoutParams deliveryStatusParams = (LinearLayout.LayoutParams) holder.deliveryStatus.getLayoutParams();
        LinearLayout.LayoutParams gifChatViewLayoutParams = (LinearLayout.LayoutParams) holder.imageViewWrapper.getLayoutParams();

        checkForGif(chatModel, holder);

        if (mCurrentUserId.equals(chatModel.getUserId())) {
            layoutParams.gravity = Gravity.RIGHT;
            layoutParams.rightMargin = Dp.toDps(mContext, 16);
            deliveryStatusParams.gravity = Gravity.RIGHT;
            gifChatViewLayoutParams.gravity = Gravity.RIGHT;

            holder.chatViewBubble.setLayoutParams(layoutParams);
            holder.imageView.setLayoutParams(gifChatViewLayoutParams);

            holder.chatViewBubble.setBackground(ContextCompat.getDrawable(mContext, R.drawable.outgoing_message_bg));
            if (chatModel.getDeliveryStatus().equals(Constants.STATUS_DELIVERED)) {
                if (position >= chatModelList.size() - 1) {
                    holder.deliveryStatus.setVisibility(View.VISIBLE);
                } else {
                    holder.deliveryStatus.setVisibility(View.INVISIBLE);
                }
                holder.deliveryStatus.setText(mContext.getString(R.string.sentText));
            } else if (chatModel.getDeliveryStatus().equals(Constants.STATUS_NOT_DELIVERED)) {
                holder.deliveryStatus.setVisibility(View.VISIBLE);
                if (updating) {
                    holder.deliveryStatus.setText(mContext.getString(R.string.sendingNowText) + percentage + " %");
                } else {
                    holder.deliveryStatus.setText(mContext.getString(R.string.sendingNowText));
                }

            }
        } else {
            holder.chatViewBubble.setBackground(ContextCompat.getDrawable(mContext, R.drawable.incoming_message_bg));
            layoutParams.gravity = Gravity.LEFT;
            gifChatViewLayoutParams.gravity = Gravity.LEFT;

            holder.chatViewBubble.setLayoutParams(layoutParams);
            holder.imageView.setLayoutParams(gifChatViewLayoutParams);
            holder.deliveryStatus.setVisibility(View.INVISIBLE);
        }

    }

A questão é que, se você notou oLog.d() continua disparando mesmo depois que o cancle e o final foram chamados no objectAnimator e sim, verifiquei se o cancelamento e o final estão sendo chamados. Então, não faço ideia do que fiz de errado. Alguém pode me ajudar?

questionAnswers(1)

yourAnswerToTheQuestion