java.lang.IncompatibleClassChangeError, После обновления плагина kotlin gradle до 1.5.20

Я хочу обновить плагин kotlin gradle с 1.4.32 к 1.5.20, Но произошла ошибка кода на устройстве с более низкой версией Android ,, например Xiaomi 5.1.1 & Oppo 6.0.1 & Pixel2 6.0, но это нормально в устройствах Android 10.

Информация об ошибке:

      java.lang.IncompatibleClassChangeError: Couldn't find com.example.kotlinupgradedemo.ProgressDialogKt.<clinit>[]
    at libcore.reflect.AnnotationAccess.indexToMethod(AnnotationAccess.java:608)
    at libcore.reflect.AnnotationAccess.getEnclosingMethodOrConstructor(AnnotationAccess.java:405)
    at java.lang.Class.isLocalClass(Class.java:1334)
    at java.lang.Class.getCanonicalName(Class.java:378)
    at androidx.lifecycle.Lifecycling.resolveObserverCallbackType(Lifecycling.java:153)
    at androidx.lifecycle.Lifecycling.getObserverConstructorType(Lifecycling.java:146)
    at androidx.lifecycle.Lifecycling.lifecycleEventObserver(Lifecycling.java:83)
    at androidx.lifecycle.LifecycleRegistry$ObserverWithState.<init>(LifecycleRegistry.java:347)
    at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.java:174)
    at com.example.kotlinupgradedemo.ProgressDialogKt.showProgress(ProgressDialog.kt:36)
    at com.example.kotlinupgradedemo.MainActivity.onCreate(MainActivity.kt:12)

Мой код ( ProgressDialog.kt):

      private val ownerToProgressMap = mutableMapOf<LifecycleOwner, Dialog>()

private val progressCleaner = object : LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun onDestroy(owner : LifecycleOwner) {
        ownerToProgressMap.remove(owner)?.dismiss()
        owner.lifecycle.removeObserver(this)
    }
}

fun LifecycleOwner.showProgress() {
    val context = when (this) {
        is Activity -> this
        is Fragment -> this.context
        else -> null
    } ?: return

    ownerToProgressMap[this]
        ?.apply { show() }
        ?: Dialog(context).also {
            it.setTitle("Tips")
            it.show()
        }.let {
            ownerToProgressMap[this] = it
            this.lifecycle.addObserver(progressCleaner)
        }
}

fun LifecycleOwner.dismissProgress() {
    ownerToProgressMap[this]?.dismiss()
}

Я просто звоню MainActivity:

      class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        showProgress()
    }
}

Полный код см. В демонстрации

1 ответ

Взгляните на AnnotationAccess.java.

Особенно линии

          try {
        return name.equals("<init>")
            ? declaringClass.getDeclaredConstructor(parametersArray)
            : declaringClass.getDeclaredMethod(name, parametersArray);
    } catch (NoSuchMethodException e) {
        throw new IncompatibleClassChangeError("Couldn't find " + declaringClass.getName()
                                               + "." + name + Arrays.toString(parametersArray));
    }

Тогда посмотрите документацию Class::getDeclaredMethod .

Возвращает объект Method, который отражает указанный объявленный метод класса или интерфейса, представленного этим объектом Class. ... Если имя - «<init>» или «<clinit>», возникает исключение NoSuchMethodException.

Инициализация глобального свойства Kotlin и свойства сопутствующего объекта компилируется в блок статической инициализации Java, также известный как <clinit>.

Головоломка завершена. Двигаться LifecycleObserver объявление из статического свойства в другом месте, и проблема будет решена.

Почему только Android 5 и 6? Я думаю это просто getDeclaredMethodразличия в реализации. Мы видим сбои только на Android 5 и 6.

Другие вопросы по тегам