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 -> {};
}
}
我是在 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 -> {};
}
}