【问题标题】:How to import Guava into Android applications如何将 Guava 导入 Android 应用程序
【发布时间】:2018-06-28 05:14:46
【问题描述】:

将 Guava 导入 Android 项目的正确方法是什么?每次我尝试使用它时,我都会收到一个NoClassDefFoundError

这就是我正在做的以产生崩溃。我正在使用 Android Studio 3.0 Canary 7。

  1. 使用Empty Activity 模板创建一个新项目File > New > New Project,目标API 26.0
  2. dependencies 部分添加到app/build.gradle

    implementation "com.google.guava:guava:20.0"
    
  3. 将此添加到MainActivity.java中的onCreate方法中

    ImmutableList<String> foo = ImmutableList.of("A", "B", "C");
    Log.d("MainActivity", foo.get(0));
    
  4. 运行 App 并打开 Logcat 看到这个异常:

    FATAL EXCEPTION: main
    Process: com.letsdoit.guavaissue, PID: 14366
    java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/common/collect/ImmutableList;
        at com.letsdoit.guavaissue.MainActivity.onCreate(MainActivity.java:20)
        at android.app.Activity.performCreate(Activity.java:6679)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
        at android.app.ActivityThread.-wrap12(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6119)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.common.collect.ImmutableList" on path: DexPathList[[zip file "/data/app/com.letsdoit.guavaissue-1/base.apk", zip file "/data/app/com.letsdoit.guavaissue-1/split_lib_dependencies_apk.apk", zip file "/data/app/com.letsdoit.guavaissue-1/split_lib_slice_0_apk.apk", zip file "/data/app/com.letsdoit.guavaissue-1/split_lib_slice_1_apk.apk", zip file "/data/app/com.letsdoit.guavaissue-1/split_lib_slice_2_apk.apk", zip file "/data/app/com.letsdoit.guavaissue-1/split_lib_slice_3_apk.apk", zip file "/data/app/com.letsdoit.guavaissue-1/split_lib_slice_4_apk.apk", zip file "/data/app/com.letsdoit.guavaissue-1/split_lib_slice_5_apk.apk", zip file "/data/app/com.letsdoit.guavaissue-1/split_lib_slice_6_apk.apk", zip file "/data/app/com.letsdoit.guavaissue-1/split_lib_slice_7_apk.apk", zip file "/data/app/com.letsdoit.guavaissue-1/split_lib_slice_8_apk.apk", zip file "/data/app/com.letsdoit.guavaissue-1/split_lib_slice_9_apk.apk"],nativeLibraryDirectories=[/data/app/com.letsdoit.guavaissue-1/lib/x86, /system/lib, /vendor/lib]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at com.letsdoit.guavaissue.MainActivity.onCreate(MainActivity.java:20) 
        at android.app.Activity.performCreate(Activity.java:6679) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) 
        at android.app.ActivityThread.-wrap12(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(ActivityThread.java:6119) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
    

我几乎可以肯定这与 Gauva 体型很大并且不能很好地使用 multidex 有关,但我不确定该怎么做。这些是我尝试过但无济于事的一些值得注意的事情:

  1. 启用multidex并在multiDexKeepFile中指定ImmutableList。

  2. 禁用即时运行。

  3. 从设备中提取 APK 并验证 Guava 类在 APK 中。

  4. 遵循此堆栈溢出question 中的建议。

【问题讨论】:

    标签: android android-studio apk guava


    【解决方案1】:

    TL;DR

    使用番石榴版本22.0-android 及更高版本。确保使用-android 风格,否则你会遇到NoClassDefFoundError

    说明

    我在发布问题后了解到如何手动清理项目并从模拟器中卸载 apk。事实证明,20.0 版本确实有效,但我在此之前尝试过21.0 版本,但未能清理。

    21.0 版本的非-android 番石榴风味使用 Java 8。21.0 之前的 android 风味和版本使用 Java 7。这在这些 release notes 22.0 版中有所描述。

    我测试了这些口味和版本:

    • 20.0 (Java 7) - 有效
    • 21.0 (Java 8) - 不起作用
    • 22.0 (Java 8) - 不起作用
    • 22.0-android (Java 7) - 有效

    当使用版本 21.022.0(没有 -android)时,ImmutableList 类被引用但未编译到 dex 文件中(因为它是斜体)。这导致了NoClassDefFoundError

    APK with dangling references to ImmutableList

    作为androiddeveloper docs解释

    在树形视图中,斜体节点是没有 在选定的 DEX 文件中定义。

    这进一步解释了

    DEX 文件可以引用在 不同的文件。例如 System.out.println() 是对 Android 框架中的 println() 方法。

    但在这种情况下,这些方法和类定义不应包含在其他文件中。只是添加它们失败。

    与使用 20.022.0-android 相比,ImmutableList 类实际上是在其中编译的。

    APK with ImmutableList defined

    应用按预期启动。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-10
      • 2011-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多