2017-03-12 3 views
4

Ich habe eine Reihe von Animations-Listener in meinem Code, wo nur eine Methode in der Schnittstelle die meiste Zeit verwendet.Verwenden von Lambda-Ausdrücken mit nicht-funktionalen Schnittstellen in Java

Also habe ich diese Wrapper:

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) { 

      } 
     }); 
    } 
} 

Auf diese Weise Code wie folgt:

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) { 

    } 
}); 

kurz wie folgt aussehen:

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

Ich frage mich nur, ob es eine bessere Möglichkeit, nicht-funktionale Schnittstellen mit einer Methode in separate Schnittstellen aufzuteilen, so dass jede Methode verwendet werden kann s unabhängig mit Lambda-Ausdrücken.

+0

Gibt es eine abstrakte AnimationAdapter-Klasse, die leere Methoden implementiert? –

Antwort

4

Statt die Animation der Verpackung würde wickelt ich den funktionalen, ein Verfahren Hörer in einen „echten“ Multi-Methode Hörer (dh die Adapter-Entwurfsmuster anzuwenden):

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 
} 

Und würden Sie nur verwenden

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

Mit einem statischen Import des Verfahrens anzupassen, wird es

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

Ich musste verschiedene Namen für die Methoden im Adapter verwenden, da der Compiler sich beschwerte, dass sie nicht eindeutig waren. 'adapt (OnAnimationStart oas)', 'adapt (OnAnimationEnd oas)' und so geändert zu 'OnAnimationStartListener (OnAnimationStart oas)', 'OnAnimationEndListener (OnAnimationEnd oas)'. – rraallvv

2

Ich würde vorschlagen, das Builder-Muster anzuwenden, um eine AnimationListener Instanz mit geeigneten Methoden zu konstruieren, die Consumer<Application> s nehmen, sie in Felder halten und diese Werte auf der letzten build Phase verwenden.

Es gibt keine Notwendigkeit, eigene Schnittstellen zu multiplizieren, da die Consumer bereits ist (und alles, was Sie schreiben könnten, ist drei neue Concumer<Animation> Kopien).

Ich bin nicht vertraut mit Android API, so schrieb ich schnell meine eigenen Klassen. Die Idee ist dieselbe.

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(); 
    } 

} 
0

prüfen AnimatorListenerAdapter aus. Dies ist eine abstrakte Klasse, die Animation.AnimationListener durch Bereitstellung von leeren Methoden implementiert. Wenn Sie AnimatorListenerAdapter erweitern, müssen Sie nur die Methoden implementieren, die Sie möchten. Solche Adapter sind ein gängiges Muster in der Java-Ereignisbehandlung.

+0

Ich denke, es wurde in API 11 hinzugefügt, ich brauche API 8. – rraallvv

Verwandte Themen