最近项目里compose 要升级到1.3, 要求compile sdk 也要到33版别,大家都知道 一般情况下,咱们修正compilesdk 都不会有什么问题,最多便是一些api的适配,编译不过啥的, 可是不会引发线上故障,可是这里要注意了target sdk 的修正 就要复杂的多了, 这里不多说,只介绍一下 我碰到的一个compilesdk 33的问题

在Compile sdk 33版别中,这个手势监听的接口 代码产生了一些改变:

谷歌的bug:当 CompileSdk 33 遇上Kotlin

在这些接口办法说 参数前面加上了一个NonNull的 注解,这个注解的意思便是 告知开发者 这个参数不行能为空

谷歌的bug:当 CompileSdk 33 遇上Kotlin

注意了 在<=32的版别中 这个注解是没有的

谷歌的bug:当 CompileSdk 33 遇上Kotlin

对于java的开发者来说,这个影响微乎其微,可是如果你跟我一样是kotlin的开发者就要倒运了,

由于在<=32的时分 你承继这个接口的时分 会提示你参数要定义成可空的

可是当你升级到33的sdk的时分,你就会发现编译不过了

谷歌的bug:当 CompileSdk 33 遇上Kotlin

为啥?

由于33的sdk 前面说过了,办法前面有了 不行空的注解了

要让他编译过很简略 咱们只要把? 去掉即可

谷歌的bug:当 CompileSdk 33 遇上Kotlin

到这里还没结束,最坑的地方来了, 尽管你能编译过,可是在运行时,有可能会产生crash

谷歌的bug:当 CompileSdk 33 遇上Kotlin

为啥? 了解kotlin的人就知道了,当你定义一个参数为不行空的类型的时分,你如果传了一个null给这个参数,他就会报这个crash了,这种情况常见于 java代码调用kotlin代码的时分 这是kotlin编译器的魔法,有爱好的可以自己反编译看一下字节码,实际上,当你定义一个变量为不行空的时分,如果传值给他 他就会校验这个值 是不是为null 为null 则直接抛反常

搞清楚问题所在今后 就得想想怎么处理了,现在的情况便是 如果不改,就编译不过,改了 在运行时会crash

别的: 这里有个链接,可以看下该问题的讨论,现在状况是显现 谷歌承认了该bug,看状况显现fixed,可是不知道为什么 还没有推送最新的33 sdk issueTracker

实际上处理这个问题的办法有很多,

办法1: 这个接口的实现 咱们不必kotlin写,用java写,即可 这个计划最简略,可是不太高雅

办法2: 魔改下android sdk 33版别的jar包,把注解去掉 这个计划也可以,可是有点麻烦

办法3: asm 字节码修正,把那个校验参数为null 就抛反常的代码删了就行了。 杀鸡焉用牛刀

办法4: 写一个delegate 即可,今后都用这个署理类去做监听, 这个办法我认为是最简略的,一了百了,并且本钱极低


import android.content.Context;
import android.os.Handler;
import android.view.GestureDetector;
import android.view.MotionEvent;
import androidx.annotation.Nullable;
/**
 * 在compile sdk 33 中 修复google的一个注解bug,该bug 会导致 要么kotlin代码编译失败
 * 要么运行时crash,这里用署理形式 简略的躲避此问题即可
 *
 */
public class GestureDetectorDelegate extends GestureDetector {
    /**
     * @param listener
     * @param handler
     * @deprecated
     */
    public GestureDetectorDelegate(OnGestureListener listener, Handler handler) {
        super(listener, handler);
    }
    /**
     * @param listener
     * @deprecated
     */
    public GestureDetectorDelegate(OnGestureListener listener) {
        super(listener);
    }
    public GestureDetectorDelegate(Context context, OnGestureListenerDelegate listener) {
        super(context, listener);
    }
    public GestureDetectorDelegate(Context context, OnGestureListener listener, Handler handler) {
        super(context, listener, handler);
    }
    public GestureDetectorDelegate(Context context, OnGestureListener listener, Handler handler, boolean unused) {
        super(context, listener, handler, unused);
    }
    /**
     * 主要修正点便是在这里了,复写这些办法 符号这些参数为可空的即可
     */
    public interface OnGestureListenerDelegate extends OnGestureListener {
        boolean onDown(@Nullable  MotionEvent e);
        void onShowPress(@Nullable   MotionEvent e);
        boolean onSingleTapUp(@Nullable   MotionEvent e);
        boolean onScroll(@Nullable  MotionEvent e1, @Nullable  MotionEvent e2, float distanceX, float distanceY);
        void onLongPress(@Nullable  MotionEvent e);
        boolean onFling(@Nullable  MotionEvent e1, @Nullable  MotionEvent e2, float velocityX, float velocityY);
    }
}