0

我是在 Android 开发中使用 RetroLamda 的新手。我了解到,选择方法取决于参数类型。我有如下界面:

interface OnCallListener {
  onSuccess(String msg);
  onError(String msg);
}

现在共同实现:

test.SetOnCallListener(new OncallListener(){
  public void onSuccess(String msg){
  ......
  }
  public void onError(String msg){
  .....
  }

});

如何在 RetroLamda 表达式中处理两种方法具有相同输入类型的这种情况?

4

1 回答 1

2

简短的回答

您可以使用默认方法并将您的侦听器子类化为只负责一种类型的事件。

长答案

我给出的答案更适合迁移具有相似品质的普通 Java 侦听器:具有多个抽象方法的接口的侦听器,偶尔也会包含不必要的样板代码,因为用户只会对处理一个特定事件感兴趣,而不是一次比他们所有人都好。

将它们与 Retrolambda 一起使用会带来一些您可能愿意或不愿意接受的权衡。更多关于这里这里

基本思想:要使监听器参数成为使用 lambda 实现的有效目标,必须确保无论监听器目标类是什么,它都应该有一个且只有一个抽象方法。考虑初始类:

public interface CallListener<T> {
  void onSuccess(T result);
  void onError(String errorMsg);
}

它有几个抽象方法,所以为了使它成为 lambda 的有效赋值目标,我们必须“实现”除一个方法之外的所有方法。我们通过使用默认方法来做到这一点:

public class CallListeners {
  public static interface SuccessListener<T> extends CallListener<T> {
    // we implement onError in such way that listener would ignore error event
    default void onError(String _ignore) {}
  }
  public static interface ErrorListener<T> extends CallListener<T> {
    default void onSuccess(T result) {}
  }

  // Methods to "help" compiler infer correct listener type
  public void <T> Call<T> success(SuccessListener<T> listener) {
    return listener;
  }
  public void <T> Call<T> error(ErrorListener<T> listener) {
    return listener;
  }
}

之后,您可以像这样使用上述所有内容:

test.SetOnCallListener(
  CallListeners.success(argument -> /*your implementation here*/));

或者

您可以创建一个允许插入其方法的各种(可能可重用)实现的具体类,并具有实用程序工厂方法,其中除了一个事件侦听器之外的所有事件侦听器都通过空操作实现:

public class CallListenerImpl<T> implements CallListener<T> {
  private Consumer<T> success; // java.util.function.Consumer
  private Consumer<String> error;
  public CallListenerImpl(Consumer<? super T> succ, Consumer<String> err) {
    success = succ; error = err;
  }
  void onSuccess(T result) {
    success.accept(result);
  }
  void onError(String err) {
    error.accept(err);
  }

  // Sugary stuffs:
  public static <T> CallListenerImpl<T> success(Consumer<T> succ) {
    return new CallListenerImpl<>(succ, noOp());
  }
  public static <T> CallListenerImpl<T> error(Consumer<String> err) {
    return new CallListenerImpl<>(noOp(), err);
  }
  private static <T> Consumer<T> noOp() {
    return a -> {};
  }
}
于 2017-04-17T20:32:27.847 回答