问题描述
将番石榴导入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.
- 使用
Empty Activity
模板创建一个新项目File> New> New Project
,目标API 26.0
. -
添加到
dependencies
部分
- Create an new project
File > New > New Project
, targetAPI 26.0
, using theEmpty Activity
template. Add to
app/build.gradle
in thedependencies
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:
-
启用multidex并在 multiDexKeepFile 中指定ImmutableList.
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)
- works21.0 (Java 8)
- doesn't work22.0 (Java 8)
- doesn't work22.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
.
作为android 开发人员文档解释
As the android developer docs explain
它进一步解释了
但是在这种情况下,这些方法和类定义没有其他文件可以结束.只是添加失败.
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.
该应用程序将按预期启动.
And the app starts up as expected.
这篇关于如何将番石榴导入Android应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!