Using lambda expressions with non-functional interfaces in Java

I have a bunch of animation listeners in my code where most of the time I used only one method in the interface.

So, I created this shell:

public class AnimationWrapper {
    private Animation mAnimation;

    public AnimationWrapper(Animation animation) {
        mAnimation = animation;
    }

    public Animation getAnimation() {
        return mAnimation;
    }

    public interface OnAnimationEnd {
        void onAnimationEnd(Animation animation);
    }

    public interface OnAnimationStart {
        void onAnimationStart(Animation animation);
    }

    public void setAnimationEndListener(OnAnimationEnd listener) {
        mAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                listener.onAnimationEnd(animation);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
    }

    public void setAnimationStartListener(OnAnimationStart listener) {
        mAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                listener.onAnimationStart(animation);
            }

            @Override
            public void onAnimationEnd(Animation animation) {

            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
    }
}

So the code is as follows:

Animation animation = AnimationUtils.loadAnimation(context, R.anim.my_animation);

animation.setAnimationListener(new Animation.AnimationListener() {
    @Override
    public void onAnimationStart(Animation animation) {

    }

    @Override
    public void onAnimationEnd(Animation animation) {
        doSomething();
    }

    @Override
    public void onAnimationRepeat(Animation animation) {

    }
});

The end is as follows:

    AnimationWrapper wrapper = new AnimationWrapper(AnimationUtils.loadAnimation(context, R.anim.my_animation));
    wrapper.setAnimationEndListener(a -> doSomething());

I'm just wondering if there is a better way to split non-functional interfaces into separate interfaces with one method so that each method can be used separately with lambda expressions.

+4
source share
3 answers

, , "", (.. ):

public interface OnAnimationEnd {
    void onAnimationEnd(Animation animation);
}

public interface OnAnimationStart {
    void onAnimationStart(Animation animation);
}

public class AnimationListeners {
    public static Animation.AnimationListener adapt(OnAnimationStart oas) {
        return new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                oas.onAnimationStart(animation);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
    }

    // same for the end
}

animation.setAnimationListener(AnimationListeners.adapt(a -> doSomething()));

animation.setAnimationListener(adapt(a -> doSomething()));
+4

AnimationListener , Consumer<Application> s, build.

, Consumer ( , , Concumer<Animation>).

Android API, . .

class Animation {}

// an analogue of the Animation.AnimationListener class
interface AnimationListener {
    void onAnimationStart(Animation animation);
    void onAnimationEnd(Animation animation);
}

class AnimationListenerBuilder {

    // do nothing by default (avoiding a NPE from the build method)
    private Consumer<Animation> onAnimationStartCallback = animation -> {};
    private Consumer<Animation> onAnimationEndCallback = animation -> {};

    public AnimationListenerBuilder setOnAnimationStartCallback(Consumer<Animation> supplier) {
        onAnimationStartCallback = supplier;
        return this;
    }

    public AnimationListenerBuilder setOnAnimationEndCallback(Consumer<Animation> supplier) {
        onAnimationEndCallback = supplier;
        return this;
    }

    private AnimationListener build() {
        return new AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                onAnimationStartCallback.accept(animation);
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                onAnimationEndCallback.accept(animation);
            }

        };
    }

    public static void main(String[] args) {

        AnimationListenerBuilder builder = new AnimationListenerBuilder();

        AnimationListener listener = builder
                .setOnAnimationEndCallback(animation -> {})
                .setOnAnimationEndCallback(animation -> {})
                .build();
    }

}
+2

Check out AnimatorListenerAdapter. This is an abstract class that implements Animation.AnimationListenerby providing empty methods. When you expand AnimatorListenerAdapter, you only need to implement the methods that you want. Such adapters are a common Java event handling scheme.

0
source

Source: https://habr.com/ru/post/1672104/


All Articles