Android kotlin 扩展错误

Android kotlin extension error

java.lang.VerifyError: .../utils/KotlinViewExtKt$animateFadeOut

在模拟器 运行 应用程序 PRE Lolipop (<21 api)

上出现该错误

导致问题的函数:

fun View.animateFadeOut(animDuration: Long = 250) {
    this.animate()
            .alpha(0F)
            .setDuration(animDuration)
            .setListener(object : Animator.AnimatorListener {

                override fun onAnimationRepeat(p0: Animator?) {}

                override fun onAnimationEnd(animation: Animator?, isReverse: Boolean) {
                    super.onAnimationEnd(animation, isReverse)
                    show(false)
                }

                override fun onAnimationEnd(p0: Animator?) {
                    show(false)
                }

                override fun onAnimationCancel(p0: Animator?) {
                }

                override fun onAnimationStart(animation: Animator?, isReverse: Boolean) {
                }

                override fun onAnimationStart(p0: Animator?) {
                }
            })
            .start()
}

fun View.show(show: Boolean) {
    val vis = if (show) View.VISIBLE else View.GONE
    if (visibility != vis) {
        visibility = vis
    }
}

指向 .setListener 行。

完美适用于 21+ api。

AS 版本:3.0.1。 Kotlin 版本:1.2.21(试过 1.1.51)。

可能是什么原因?我的坏还是科特林? Multidex 已启用。

解决方案

基于this issue and this fix:

ViewExtension.kt

fun View.animateFadeOut(animDuration: Long = 250L) {
    this.animate()
            .alpha(0F)
            .setDuration(animDuration)
            .setListener(object : AbstractAnimatorListener() {

                override fun onAnimationEnd(animation: Animator?, isReverse: Boolean) {
                    super.onAnimationEnd(animation, isReverse)
                    show(false)
                }

                override fun onAnimationEnd(p0: Animator?) {
                    show(false)
                }
            })
            .start()
}

fun View.show(show: Boolean) {
    val vis = if (show) View.VISIBLE else View.GONE
    if (visibility != vis) {
        visibility = vis
    }
}

AbstractAnimatorListener.kt

abstract class AbstractAnimatorListener : Animator.AnimatorListener {

    override fun onAnimationRepeat(p0: Animator?) {}

    override fun onAnimationEnd(p0: Animator?) {}

    override fun onAnimationCancel(p0: Animator?) {}

    override fun onAnimationStart(p0: Animator?) {}

    override fun onAnimationEnd(animation: Animator?, isReverse: Boolean) {
        onAnimationEnd(animation)
    }

    override fun onAnimationStart(animation: Animator?, isReverse: Boolean) {
        onAnimationStart(animation)
    }
}

说明

尝试使用 Java 8 默认值删除 API 26 中添加的这些方法并使用替代动画:

Animator.AnimatorListener:

onAnimationEnd added in API level 26

void onAnimationEnd (Animator animation, boolean isReverse)

onAnimationStart added in API level 26

void onAnimationStart (Animator animation, boolean isReverse)

可以重写这些方法,但不是必需的,以便在动画开始时获取额外的播放方向信息。

AnimatorSet:

Starting in Android 8.0 (API 26) the AnimatorSet API supports seeking and playing in reverse.


注:

/**
 * Skipping calling super when overriding this method results in
 * {@link #onAnimationStart(Animator)} not getting called.
 */
default void onAnimationStart(Animator animation, boolean isReverse) {
    onAnimationStart(animation);
}

我需要将 添加到我的 build.gradle 文件中以进行测试

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
  kotlinOptions {
    jvmTarget = "1.8"
  }
}

或替换

super.onAnimationEnd(animation, isReverse)

来自

onAnimationEnd(animation)

避免错误:

Super calls to Java default methods are prohibited in JVM target 1.6. Recompile with '-jvm-target 1.8'

并将下一行添加到我的 gradle.properties 文件

android.enableD8=true

避免异常:

com.android.dx.cf.code.SimException: default or static interface method used without --min-sdk-version >= 24

现在编译,刚刚启动 kitKat 模拟器...

有效,我的项目中也启用了 MultiDex。

抱歉,我无法重现。

或者,使用 Java 8 个默认值删除这两种方法,它也有效。


注2:

Arpan 关于 AnimatorListenerAdapter 的建议可行,但没有必要。

您可以删除那些方法,更改动画并创建:

object EmptyAnimatorListener : Animator.AnimatorListener {
    override fun onAnimationRepeat(p0: Animator?) {}
    override fun onAnimationEnd(p0: Animator?) {}
    override fun onAnimationCancel(p0: Animator?) {}
    override fun onAnimationStart(p0: Animator?) {}
}

并像这样使用委托:

    .setListener(object : Animator.AnimatorListener by EmptyAnimatorListener {
        override fun onAnimationStart(animation: Animator) {
            // Do something
        }

        override fun onAnimationEnd(animation: Animator) {
            // Do something
        }
    })

注3:

转载将其添加到扩展函数中:

E/AndroidRuntime: FATAL EXCEPTION: main Process: ...android, PID: 3409 java.lang.VerifyError: com/.../ui/common/extension/android/view/ViewExtensionKt$animateFadeOut

  • 使用 Java 默认值删除 Api 26 种方法可解决问题。

  • 替换调用 onAnimationEnd 的超级调用也解决了它:

        override fun onAnimationEnd(animation: Animator?, isReverse: Boolean) {
            onAnimationEnd(animation)
        }
    
  • 调用super.onAnimationStart(animation: Animator?, isReverse: Boolean) 需要API 26:

  • 反编译 Kotlin 字节码显示无法解析这些方法: