问题 包含espresso-contrib:2.0时的java.lang.IncompatibleClassChangeError


我有一个android.support.v7.widget.RecyclerView的子类。当我使用应用程序和测试时,它工作正常。

但是,当我在gradle app文件中包含espresso-contrib时,当我尝试运行相同的测试时,我得到一个例外。该应用仍然有效。在arm模拟器和设备上的sdk版本21和22中都会出现同样的问题。使用x86模拟器,它会发生段错误。

摇篮

androidTestCompile 'com.android.support.test.espresso:espresso-contrib:2.0'

例外

java.lang.IncompatibleClassChangeError: xxx.DashboardActivity$1
at dalvik.system.DexFile.defineClassNative(Native Method)
at dalvik.system.DexFile.defineClass(DexFile.java:226)
at dalvik.system.DexFile.loadClassBinaryName(DexFile.java:219)
at dalvik.system.DexPathList.findClass(DexPathList.java:321)
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:54)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
at xxx.DashboardActivity.onCreate(DashboardActivity.java:54)
at android.app.Activity.performCreate(Activity.java:5990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.support.test.runner.MonitoringInstrumentation.callActivityOnCreate(MonitoringInstrumentation.java:346)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

adb logcat

I/ActivityManager( 1229): START u0 {act=android.intent.action.MAIN flg=0x14000000 cmp=xxx/.activities.DashboardActivity} from uid 10059 on display 0
V/WindowManager( 1229): addAppToken: AppWindowToken{65964e3 token=Token{3f63d512 ActivityRecord{19743c9d u0 xxx/.activities.DashboardActivity t13}}} to stack=1 task=13 at 0
D/LifecycleMonitor( 2953): Lifecycle status change: xxx.activities.DashboardActivity@281384ef in: PRE_ON_CREATE
V/WindowManager( 1229): Adding window Window{2d974c1a u0 Starting xxx} at 2 of 7 (after Window{27a98488 u0 com.android.launcher/com.android.launcher2.Launcher})
W/RecyclerView( 2953): setScrollingTouchSlop(): bad argument constant 315513600; using default value
W/art     ( 2953): Incompatible structural change detected: Structural change of android.support.v7.widget.RecyclerView$Adapter is hazardous (/data/dalvik-cache/x86/data@app@xxx-1@b
ase.apk@classes.dex at compile time, /data/dalvik-cache/x86/data@app@xxx.test-1@base.apk@classes.dex at runtime): Virtual method count off: 26 vs 25
W/art     ( 2953): Landroid/support/v7/widget/RecyclerView$Adapter; (Compile time):
W/art     ( 2953):  Static fields:
W/art     ( 2953):  Instance fields:
W/art     ( 2953):   Z mHasStableIds
W/art     ( 2953):   Landroid/support/v7/widget/RecyclerView$AdapterDataObservable; mObservable
W/art     ( 2953):  Direct methods:
W/art     ( 2953):   <init>()V
W/art     ( 2953):  Virtual methods:
W/art     ( 2953):   bindViewHolder(Landroid/support/v7/widget/RecyclerView$ViewHolder;I)V
W/art     ( 2953):   createViewHolder(Landroid/view/ViewGroup;I)Landroid/support/v7/widget/RecyclerView$ViewHolder;
W/art     ( 2953):   getItemCount()I
W/art     ( 2953):   getItemId(I)J
W/art     ( 2953):   getItemViewType(I)I
W/art     ( 2953):   hasObservers()Z
W/art     ( 2953):   hasStableIds()Z
W/art     ( 2953):   notifyDataSetChanged()V
W/art     ( 2953):   notifyItemChanged(I)V
W/art     ( 2953):   notifyItemInserted(I)V
W/art     ( 2953):   notifyItemMoved(II)V
W/art     ( 2953):   notifyItemRangeChanged(II)V
W/art     ( 2953):   notifyItemRangeInserted(II)V
W/art     ( 2953):   notifyItemRangeRemoved(II)V
W/art     ( 2953):   notifyItemRemoved(I)V
W/art     ( 2953):   onAttachedToRecyclerView(Landroid/support/v7/widget/RecyclerView;)V
W/art     ( 2953):   onBindViewHolder(Landroid/support/v7/widget/RecyclerView$ViewHolder;I)V
W/art     ( 2953):   onCreateViewHolder(Landroid/view/ViewGroup;I)Landroid/support/v7/widget/RecyclerView$ViewHolder;
W/art     ( 2953):   onDetachedFromRecyclerView(Landroid/support/v7/widget/RecyclerView;)V
W/art     ( 2953):   onFailedToRecycleView(Landroid/support/v7/widget/RecyclerView$ViewHolder;)Z
W/art     ( 2953):   onViewAttachedToWindow(Landroid/support/v7/widget/RecyclerView$ViewHolder;)V
W/art     ( 2953):   onViewDetachedFromWindow(Landroid/support/v7/widget/RecyclerView$ViewHolder;)V
W/art     ( 2953):   onViewRecycled(Landroid/support/v7/widget/RecyclerView$ViewHolder;)V
W/art     ( 2953):   registerAdapterDataObserver(Landroid/support/v7/widget/RecyclerView$AdapterDataObserver;)V
W/art     ( 2953):   setHasStableIds(Z)V
W/art     ( 2953):   unregisterAdapterDataObserver(Landroid/support/v7/widget/RecyclerView$AdapterDataObserver;)V
W/art     ( 2953): Landroid/support/v7/widget/RecyclerView$Adapter; (Runtime):
W/art     ( 2953):  Static fields:
W/art     ( 2953):  Instance fields:
W/art     ( 2953):   Z mHasStableIds
W/art     ( 2953):   Landroid/support/v7/widget/RecyclerView$AdapterDataObservable; mObservable
W/art     ( 2953):  Direct methods:
W/art     ( 2953):   <init>()V
W/art     ( 2953):  Virtual methods:
W/art     ( 2953):   bindViewHolder(Landroid/support/v7/widget/RecyclerView$ViewHolder;I)V
W/art     ( 2953):   createViewHolder(Landroid/view/ViewGroup;I)Landroid/support/v7/widget/RecyclerView$ViewHolder;
W/art     ( 2953):   getItemCount()I
W/art     ( 2953):   getItemId(I)J
W/art     ( 2953):   getItemViewType(I)I
W/art     ( 2953):   hasObservers()Z
W/art     ( 2953):   hasStableIds()Z
W/art     ( 2953):   notifyDataSetChanged()V
W/art     ( 2953):   notifyItemChanged(I)V
W/art     ( 2953):   notifyItemInserted(I)V
W/art     ( 2953):   notifyItemMoved(II)V
W/art     ( 2953):   notifyItemRangeChanged(II)V
W/art     ( 2953):   notifyItemRangeInserted(II)V
W/art     ( 2953):   notifyItemRangeRemoved(II)V
W/art     ( 2953):   notifyItemRemoved(I)V
W/art     ( 2953):   onAttachedToRecyclerView(Landroid/support/v7/widget/RecyclerView;)V
W/art     ( 2953):   onBindViewHolder(Landroid/support/v7/widget/RecyclerView$ViewHolder;I)V
W/art     ( 2953):   onCreateViewHolder(Landroid/view/ViewGroup;I)Landroid/support/v7/widget/RecyclerView$ViewHolder;
W/art     ( 2953):   onDetachedFromRecyclerView(Landroid/support/v7/widget/RecyclerView;)V
W/art     ( 2953):   onViewAttachedToWindow(Landroid/support/v7/widget/RecyclerView$ViewHolder;)V
W/art     ( 2953):   onViewDetachedFromWindow(Landroid/support/v7/widget/RecyclerView$ViewHolder;)V
W/art     ( 2953):   onViewRecycled(Landroid/support/v7/widget/RecyclerView$ViewHolder;)V
W/art     ( 2953):   registerAdapterDataObserver(Landroid/support/v7/widget/RecyclerView$AdapterDataObserver;)V
W/art     ( 2953):   setHasStableIds(Z)V
W/art     ( 2953):   unregisterAdapterDataObserver(Landroid/support/v7/widget/RecyclerView$AdapterDataObserver;)V
I/art     ( 2953): Rejecting re-init on previously-failed class java.lang.Class<xxx.models.JSONArrayRecyclerViewAdapter>
I/art     ( 2953): Rejecting re-init on previously-failed class java.lang.Class<xxx.models.JSONArrayRecyclerViewAdapter>
I/art     ( 2953): Rejecting re-init on previously-failed class java.lang.Class<xxx.activities.DashboardActivity$1>
I/art     ( 2953): Rejecting re-init on previously-failed class java.lang.Class<xxx.activities.DashboardActivity$1>
D/AndroidRuntime( 2953): Shutting down VM
E/MonitoringInstrumentation( 2953): Exception encountered by: Thread[main,5,main]. Dumping thread state to outputs and pining for the fjords.
E/MonitoringInstrumentation( 2953): java.lang.IncompatibleClassChangeError: xxx.activities.DashboardActivity$1
E/MonitoringInstrumentation( 2953):     at dalvik.system.DexFile.defineClassNative(Native Method)
E/MonitoringInstrumentation( 2953):     at dalvik.system.DexFile.defineClass(DexFile.java:226)
E/MonitoringInstrumentation( 2953):     at dalvik.system.DexFile.loadClassBinaryName(DexFile.java:219)
E/MonitoringInstrumentation( 2953):     at dalvik.system.DexPathList.findClass(DexPathList.java:321)
E/MonitoringInstrumentation( 2953):     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:54)
E/MonitoringInstrumentation( 2953):     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
E/MonitoringInstrumentation( 2953):     at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
E/MonitoringInstrumentation( 2953):     at xxx.activities.DashboardActivity.onCreate(DashboardActivity.java:54)
E/MonitoringInstrumentation( 2953):     at android.app.Activity.performCreate(Activity.java:5990)
E/MonitoringInstrumentation( 2953):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
E/MonitoringInstrumentation( 2953):     at android.support.test.runner.MonitoringInstrumentation.callActivityOnCreate(MonitoringInstrumentation.java:346)
E/MonitoringInstrumentation( 2953):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
E/MonitoringInstrumentation( 2953):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
E/MonitoringInstrumentation( 2953):     at android.app.ActivityThread.access$800(ActivityThread.java:151)
E/MonitoringInstrumentation( 2953):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
E/MonitoringInstrumentation( 2953):     at android.os.Handler.dispatchMessage(Handler.java:102)
E/MonitoringInstrumentation( 2953):     at android.os.Looper.loop(Looper.java:135)
E/MonitoringInstrumentation( 2953):     at android.app.ActivityThread.main(ActivityThread.java:5257)
E/MonitoringInstrumentation( 2953):     at java.lang.reflect.Method.invoke(Native Method)
E/MonitoringInstrumentation( 2953):     at java.lang.reflect.Method.invoke(Method.java:372)
E/MonitoringInstrumentation( 2953):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
E/MonitoringInstrumentation( 2953):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

4041
2018-03-23 17:16


起源

这好像是 onFailedToRecycleView(Landroid/support/v7/widget/RecyclerView$ViewHolder;)  是不同的。我的猜测是espresso-contrib试图替换类或接口但是没有实现所有方法?我还是不知道如何解决它。 - seppo0010


答案:


浓咖啡依赖已过时。报告并将在未来修复。 https://code.google.com/p/android-test-kit/issues/detail?id=139


12
2018-04-02 22:22



关于这个的任何更新? - Christopher Francisco
相反,目前有解决方法吗? - John Shelley
@JohnShelley我能够通过排除espresso-contrib库尝试使用的Recyclerview模块来解决这个问题。 androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.2'){排除模块:'support-annotations'排除模块:'recyclerview-v7'} - jacobduron
不能再编辑上面的评论,我在上面写错了。正确的行是:androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.2'){排除模块:'support-annotations'排除模块:'support-v4'排除模块:'support-v13 '排除模块:'recyclerview-v7'} - jacobduron


请用 最新的Gradle插件 (不是稳定的版本)

从Android Gradle插件的2.0.0开始,如果主APK和测试APK使用相同的库(例如Guava)但是在不同的版本中,Gradle构建将失败。

要使构建成功,只需将新版本的依赖项添加到 build.gradle

例如:

androidTestCompile "com.android.support:recyclerview-v7:${supportLibVersion}"

参考:


0
2018-03-14 10:24





您可以尝试在gradle文件的底部添加(在每个char之后)

/*
Resolves dependency versions across test and production APKs, specifically, transitive
dependencies. This is required since Espresso internally has a dependency on support-annotations.
*/
configurations.all {
    resolutionStrategy.force "com.android.support:support-annotations:$rootProject.supportLibraryVersion"
}

/*
All direct/transitive dependencies shared between your test and production APKs need to be
excluded from the test APK! This is necessary because both APKs will contain the same classes. Not
excluding these dependencies from your test configuration will result in an dex pre-verifier error
at runtime. More info in this tools bug: (https://code.google.com/p/android/issues/detail?id=192497)
*/
configurations.compile.dependencies.each { compileDependency ->
    println "Excluding compile dependency: ${compileDependency.getName()}"
    configurations.androidTestCompile.dependencies.each { androidTestCompileDependency ->
        configurations.androidTestCompile.exclude module: "${compileDependency.getName()}"
    }
}

它来自github上的Android测试项目

资源: https://github.com/googlecodelabs/android-testing/blob/master/app/build.gradle#L96


0
2018-04-12 18:39





也许你忘了添加 testInstrumentationRunner android.support.test.runner.AndroidJUnitRunner“in defaultConfig {}


0
2017-12-14 15:39