Android RetroLamda 实现概率

Android RetroLamda implementation prob

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

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

现在共同实施:

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

});

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

简答:

您可以使用默认方法和子class您的侦听器只对一种类型的事件负责。

长答案:

我给出的答案更适合迁移具有相似特性的普通 Java 侦听器:具有具有多个抽象方法的接口的侦听器,偶尔也会包含不必要数量的样板文件,因为用户会只对处理一个特定事件感兴趣,而不是同时处理所有事件。

将它们与 Retrolambda 一起使用需要进行一些权衡,您可能愿意也可能不愿意接受这些权衡。关于此的更多信息 here and here.

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

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

它有几个抽象方法,因此要使其成为 lambda 的有效赋值目标,我们必须 "implement" 除了一个方法之外的所有方法。我们使用默认方法来做到这一点:

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*/));

或者:

您可以制作一个具体的 class 允许插入其方法的各种(可能可重用的)实现,并具有实用工厂方法,其中除一个事件侦听器外的所有事件侦听器均由空操作实现:

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 -> {};
  }
}