背景
我在安卓系统上做一些大型项目,最初是100%用Java编写的。当我将一些文件转换为Kotlin时,我发现至少有两种情况是文档和代码声明某些函数的一些参数应该是非null的,所以我也让它们在Kotlin上保持这种状态:
- https://developer.android.com/reference/android/view/GestureDetector.OnGestureListener#onFling(android.view.MotionEvent,%20android.vview.MotionEvents,%20float,%20浮点(
- https://developer.android.com/reference/android/view/GestureDetector.SimpleOnGestureListener#onFling(android.view.MotionEvent,%20android.vview.MotionEvents,%20float,%20浮点(
意味着它们看起来是这样的:
boolean onFling(@NonNull MotionEvent e1, @NonNull MotionEvent e2, float velocityX, float velocityY);
问题
我通过Crashlytics注意到,这两种情况实际上会导致一些设备崩溃,因为它们实际上得到了null值,因为Kotlin对这件事很严格(当参数设置为非null时得到null(。
我尝试过的
我已经在问题跟踪器上报告了这一点(此处和这里(,我试图找到如何强制Kotlin允许参数为null,尽管后面的代码说它们不是。可悲的是,它总是会导致"onFling‘什么都不覆盖’;,并且不让我建造它。
我找不到如何做到这一点,所以现在,我使用Java。意思是这样的:
public class SimpleOnGestureListenerCompat extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onFling(@Nullable final MotionEvent e1, @Nullable final MotionEvent e2, final float velocityX, final float velocityY) {
return super.onFling(e1, e2, velocityX, velocityY);
}
}
我还添加了Crashlytics来告诉我第二个参数是否也可以为null,这就是为什么我也将其设置为可以为null的原因。
问题
- 这是我目前唯一可以使用的解决方法吗?我不能用Kotlin吗?也许可以使用一些注释,在运行时为我将要创建的扩展这些有问题的类的新类删除可为null的检查
- 这是否只是因为Android Studio对Java的可空性处理得不太好/严格,或者这总是Java的一种可能的解决方法?它甚至没有向我显示使用错误注释的警告
我已经在Java中创建了自己的SimpleOnGestureListener(名为KotlinAdapterOnGesture Listener(作为一个方便类,然后我可以将Kotlin用于我真正的OnGesturerListener,扩展KotlinAdapter OnGestuerListener并覆盖onMoveKt和onFlingKt,而不是onMove和onFling:
public class KotlinAdapterOnGestureListener implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener {
public boolean onSingleTapUp(@NonNull MotionEvent e) {
return false;
}
public void onLongPress(@NonNull MotionEvent e) {
}
/** Instead of overwriting this method, overwrite onScrollKt, because despite
* the annotation, the parameter e1 is sometimes null. */
final public boolean onScroll(@NonNull MotionEvent e1, @NonNull MotionEvent e2,
float distanceX, float distanceY) {
return onScrollKt(e1, e2, distanceX, distanceY);
}
public boolean onScrollKt(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
return false;
}
/** Instead of overwriting this method, overwrite onFlingKt, because despite
* the annotation, the parameter e1 is sometimes null. */
final public boolean onFling(@NonNull MotionEvent e1, @NonNull MotionEvent e2, float velocityX,
float velocityY) {
return onFlingKt(e1, e2, velocityX, velocityY);
}
public boolean onFlingKt(MotionEvent e1, MotionEvent e2,
float velocityX, float velocityY) {
return false;
}
public void onShowPress(@NonNull MotionEvent e) {
}
public boolean onDown(@NonNull MotionEvent e) {
return false;
}
public boolean onDoubleTap(@NonNull MotionEvent e) {
return false;
}
public boolean onDoubleTapEvent(@NonNull MotionEvent e) {
return false;
}
public boolean onSingleTapConfirmed(@NonNull MotionEvent e) {
return false;
}
}
至少如果你有多个OnGestureListener,你只需要在Java中有这一个类;真实的";编码仍在Kotlin。
这应该适用于IMO。没有经过大量测试,但应该同时适用于java
和kotlin
。此外,可以由通过自定义GestureDetector.OnGestureListener
或如果类本身实现GestureDetector.OnGestureListener
的两者使用
public interface SafeOnGestureListener extends GestureDetector.OnGestureListener {
@Override
boolean onScroll(@Nullable MotionEvent e1, @Nullable MotionEvent e2, float distanceX,
@Override
boolean onFling(@Nullable MotionEvent e1, @Nullable MotionEvent e2, float velocityX,
float velocityY);
}
这是我们的临时修复:
首先是Class标头/协议声明:
@Suppress("ABSTRACT_MEMBER_NOT_IMPLEMENTED")
class ActivityMain : AppCompatActivity(),
GestureDetector.OnGestureListener
第二种方法实现:
@Suppress("ACCIDENTAL_OVERRIDE")
fun onScroll(
p0: MotionEvent?,
p1: MotionEvent,
distanceX: Float,
distanceY: Float
): Boolean {
return true
}
请注意,在onScroll实现之前没有覆盖,因为没有任何内容被覆盖。我们添加了"MotionEvent之后。
结果;onScroll"将接受空的MotionEvents。