使用 Instant 时出现 VerifyError 运行

VerifyError when using Instant Run

当达到 XpInsetDrawable.create(Drawable, int)(下面的代码)时抛出 VerifyError。当 not 使用 Instant 运行.

时,不会发生这种情况

我正在使用 Android Studio 2.0.0 和 gradle 构建插件 2.0.0。在 SDK 22 上测试。当在 SDK 19 模拟器上 运行 时,整个模拟器会重新启动。

我正在寻找 "disable Instant Run" 以外的解决方案。

Exception(整个堆栈跟踪不相关)

Caused by: java.lang.VerifyError:
Verifier rejected class net.xpece.android.support.preference.XpInsetDrawable due to bad method
java.lang.Object net.xpece.android.support.preference.XpInsetDrawable.access$super(
    net.xpece.android.support.preference.XpInsetDrawable,
    java.lang.String,
    java.lang.Object[])
(declaration of 'net.xpece.android.support.preference.XpInsetDrawable'
appears in /data/data/net.xpece.android.support.preference.sample/files/instant-run/dex/slice-slice_7-classe

Class源代码

final class XpInsetDrawable extends InsetDrawable {
    private static final boolean NEEDS_FIXING = Build.VERSION.SDK_INT < 21;

    private final Rect mInset = new Rect();

    public static InsetDrawable create(final Drawable drawable, final int insetLeft, final int insetTop, final int insetRight, final int insetBottom) {
        if (NEEDS_FIXING) {
            return new XpInsetDrawable(drawable, insetLeft, insetTop, insetRight, insetBottom);
        } else {
            return new InsetDrawable(drawable, insetLeft, insetTop, insetRight, insetBottom);
        }
    }

    public static InsetDrawable create(final Drawable drawable, final int inset) {
        if (NEEDS_FIXING) {
            return new XpInsetDrawable(drawable, inset);
        } else {
            return new InsetDrawable(drawable, inset);
        }
    }

    XpInsetDrawable(final Drawable drawable, final int inset) {
        super(drawable, inset);
        mInset.set(inset, inset, inset, inset);
    }

    XpInsetDrawable(final Drawable drawable, final int insetLeft, final int insetTop, final int insetRight, final int insetBottom) {
        super(drawable, insetLeft, insetTop, insetRight, insetBottom);
        mInset.set(insetLeft, insetTop, insetRight, insetBottom);
    }

    @Override
    public int getIntrinsicHeight() {
        return super.getIntrinsicHeight() + mInset.top + mInset.bottom;
    }

    @Override
    public int getIntrinsicWidth() {
        return super.getIntrinsicWidth() + mInset.left + mInset.right;
    }
}

2016-08-25 更新: Android Studio 2.2-beta3 中发布的修复。


更新 2016-07-15: 修复的目标版本现在是 Android Studio 2.3。


我用 Android 提交了一个错误,这是开发人员 j...@google.com 不得不说的:

Interesting !

The XpInsetDrawable is a subclass of InsetDrawable which parent has changed in 23. Starting in 23, InsetDrawable subclasses DrawableWrapper which was added in 23. The app is compiled with CompileSdkVersion 23 so we generate method accesses for the DrawableWrapper methods.

now when running on <23, these methods do no exist, in fact the class does not exist so we blow up.

workaround for now is to have compileSdkVersion set to a lower version or run the application on 23 when in InstantRun mode.

potential fix is to instrument against the targeted device API level android.jar rather than the compileSdkVersion one. This is too involving for 2.1, targeted to 2.2.

来源:https://code.google.com/p/android/issues/detail?id=206746


这意味着在 Android Studio 2.2 发布之前,我不能同时继承 InsetDrawable 和使用 Instant 运行。

我会考虑将 SDK 22 InsetDrawable 直接复制到我的项目中。