Search code examples
androidobjectanimator

Passing ObjectAnimator as a parameter not working


I made "heart beat effect button"(Continuous blinking) using ObjectAnimator, And it works fine.

There is 4 buttons, named btn1RT, btn2LT, btn3LB and btn4RB. If one of the button starts blinking, other buttons will be disappeared.

Question: I refactored this code, and it does not working anymore. I can't stop buttons from blinking, so all of my buttons are blinking. I want to know why these buttons cannot be stopped.

I think passing ObjectAnimator as a parameter is problem, but there is no clue.

Any help will be appreciated.

Before:

private void start1HeartBeat() {
        oa1 = ObjectAnimator.ofFloat(btn1RT, "alpha", 1, 0);
        oa1.setDuration(HEARTBEAT_RUN_DURATION);
        oa1.setRepeatCount(ValueAnimator.INFINITE);
        oa1.setRepeatMode(ValueAnimator.REVERSE);
        oa1.start();

        if (oa2.isRunning()) {
            oa2.end();
            oa2 = ObjectAnimator.ofFloat(btn2LT, "alpha", 0.5f, 0);
            oa2.setDuration(HEARTBEAT_STOP_DURATION);
            oa2.setRepeatCount(0);
            oa2.setRepeatMode(ValueAnimator.RESTART);
            oa2.start();
        }

        if (oa3.isRunning()) {
            oa3.end();
            oa3 = ObjectAnimator.ofFloat(btn3LB, "alpha", 0.5f, 0);
            oa3.setDuration(HEARTBEAT_STOP_DURATION);
            oa3.setRepeatCount(0);
            oa3.setRepeatMode(ValueAnimator.RESTART);
            oa3.start();
        }

        if (oa4.isRunning()) {
            oa4.end();
            oa4 = ObjectAnimator.ofFloat(btn4RB, "alpha", 0.5f, 0);
            oa4.setDuration(HEARTBEAT_STOP_DURATION);
            oa4.setRepeatCount(0);
            oa4.setRepeatMode(ValueAnimator.RESTART);
            oa4.start();
        }
    }
}

After refactored: this is not working.

private void start1HeartBeat() {
    startHeartBeat(oa1, btn1RT);
    stopHeartBeat(oa2, btn2LT);
    stopHeartBeat(oa3, btn3LB);
    stopHeartBeat(oa4, btn4RB);
}

private synchronized void startHeartBeat(ObjectAnimator oa, Object btn) {
        oa = ObjectAnimator.ofFloat(btn, "alpha", 1, 0);
        oa.setDuration(HEARTBEAT_RUN_DURATION);
        oa.setRepeatCount(ValueAnimator.INFINITE);
        oa.setRepeatMode(ValueAnimator.REVERSE);
        oa.start();
    }

private synchronized void stopHeartBeat(ObjectAnimator oa, Object btn) {
    if (oa.isRunning()) {
        oa.end();
        oa = ObjectAnimator.ofFloat(btn, "alpha", 0.5f, 0);
        oa.setDuration(HEARTBEAT_STOP_DURATION);
        oa.setRepeatCount(0);
        oa.setRepeatMode(ValueAnimator.RESTART);
        oa.start();
    }
}

Solution

  • To understand the problem we should be clear about the difference between pass-by-value and pass-by-reference. For the case of Java, this post better clarifies the concept.

    In short, in Java the reference itself is pass-by-value. As we know in pass-by-value the change inside a method is not reflected outside. Hence changing the passed reference inside a method is not reflected outside.

    With this knowledge, one of the way to correctly refactor the code is as follows

    private void start1HeartBeat() {
        oa1 = startHeartBeat(oa1, btn1RT);
        oa2 = stopHeartBeat(oa2, btn2LT);
        oa3 = stopHeartBeat(oa3, btn3LB);
        oa4 = stopHeartBeat(oa4, btn4RB);
    }
    
    private synchronized ObjectAnimator startHeartBeat(ObjectAnimator oa, Object btn) {
        oa = ObjectAnimator.ofFloat(btn, "alpha", 1, 0);
        oa.setDuration(HEARTBEAT_RUN_DURATION);
        oa.setRepeatCount(ValueAnimator.INFINITE);
        oa.setRepeatMode(ValueAnimator.REVERSE);
        oa.start();
        return oa;
    }
    
    private synchronized ObjectAnimator stopHeartBeat(ObjectAnimator oa, Object btn) {
        if (oa.isRunning()) {
            oa.end();
            oa = ObjectAnimator.ofFloat(btn, "alpha", 0.5f, 0);
            oa.setDuration(HEARTBEAT_STOP_DURATION);
            oa.setRepeatCount(0);
            oa.setRepeatMode(ValueAnimator.RESTART);
            oa.start();
        }
        return oa;
    }
    

    I just mentioned one possible way to refactor. Since the core problem is clarified, you do refactor in an appropriate way.