如何将番石榴导入Android应用程序 [英] How to import Guava into Android applications

查看:68
本文介绍了如何将番石榴导入Android应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将番石榴导入Android项目的正确方法是什么?每次尝试使用它时,都会得到一个 NoClassDefFoundError .

What is the proper way to import Guava into an Android project? Every time I try to use it I get a NoClassDefFoundError.

这就是我要生成崩溃的原因.我正在使用Android Studio 3.0 Canary 7.

This is what I'm doing to generate the crash. I'm using Android Studio 3.0 Canary 7.

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

  1. Create an new project File > New > New Project, target API 26.0, using the Empty Activity template.
  2. Add to app/build.gradle in the dependencies section

implementation "com.google.guava:guava:20.0"

  • 将此添加到 MainActivity.java

    ImmutableList<String> foo = ImmutableList.of("A", "B", "C");
    Log.d("MainActivity", foo.get(0));
    

  • 运行应用程序并打开Logcat以查看此异常:

  • Run the App and open up Logcat to see this exception:

    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的表现不佳有关,但不确定如何处理.这些是我没有用的值得注意的事情:

    I'm almost certain it has to do with Gauva being large and not playing well with multidex, but am not sure what to do about it. These are some of the note worthy things I've tried to no avail:

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

    1. Enabling multidex and specifying ImmutableList in the multiDexKeepFile.

    禁用即时运行.

    从设备中拉出APK,并验证番石榴类是否在APK中.

    Pulled the APKs from the device and verified the Guava classes are in the APKs.

    遵循此堆栈溢出中的建议

    Following the recommendations in this stack overflow question.

    推荐答案

    TL; DR

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

    Use guava version 22.0-android and up. Make sure to use the -android flavor, otherwise you'll run into the NoClassDefFoundError.

    说明

    发布问题后,我学会了如何手动清理项目并从模拟器中卸载apk.事实证明, 20.0 版本确实可以工作,但是在此之前我曾尝试过 21.0 版本,但无法清除.

    I learned after posting the question how to manually clean the project and uninstall apks from the emulator. It turns out that version 20.0 actually does work, but I had tried version 21.0 right before then and failed to clean.

    版本为 21.0 的番石榴的非 -android 版本使用Java8. 21.0 之前的android版本和版本使用Java 7在这些发行说明(版本22.0)中进行了描述.

    The non-android flavors of guava as of version 21.0 are using Java 8. The android flavors and versions before 21.0 use Java 7. This is described in these release notes for version 22.0.

    我测试了以下口味和版本:

    I tested these flavors and versions:

    • 20.0(Java 7)-有效
    • 21.0(Java 8)-不起作用
    • 22.0(Java 8)-不起作用
    • 22.0-android(Java 7)-有效
    • 20.0 (Java 7) - works
    • 21.0 (Java 8) - doesn't work
    • 22.0 (Java 8) - doesn't work
    • 22.0-android (Java 7) - works

    使用版本 21.0 22.0 (无 -android )时, ImmutableList 类被引用,但未引用编译成dex文件(因为它是斜体).这导致 NoClassDefFoundError .

    When using version 21.0 or 22.0 (no -android) the ImmutableList class is getting referenced but not compiled into the dex files (since it's in italics). This was causing the NoClassDefFoundError.

    APK带有对ImmutableList的悬挂引用

    作为android 开发人员文档解释

    As the android developer docs explain

    在树形视图中,斜体节点是不具有引用的引用所选DEX文件中的定义.

    In the tree view, italicized nodes are references that do not have a definition in the selected DEX file.

    它进一步解释了

    DEX文件可以引用在.NET中定义的方法和字段.不同的文件.例如System.out.println()是对Android框架中的println()方法.

    A DEX file can reference methods and fields that are defined in a different a file. For example System.out.println() is a reference to the println() method in the Android framework.

    但是在这种情况下,这些方法和类定义没有其他文件可以结束.只是添加失败.

    But in this case, there is no other file that these methods and class definition should end up in. It's just failing to add them.

    与使用 20.0 22.0-android (实际上在其中编译ImmutableList类)相反.

    Contrast that to using 20.0 or 22.0-android, where the ImmutableList class actually gets compiled in.

    定义了ImmutableList的APK

    该应用程序将按预期启动.

    And the app starts up as expected.

    这篇关于如何将番石榴导入Android应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆