[英]java.lang.NoClassDefFoundError: Failed resolution of: Lretrofit2/Retrofit$Builder;
我正在努力在 Android 中编写非常简单的基于 Retrofit2 的 Instrumented 测试(connectedTestAndroid 任务)。
然而,由于上述简短的错误消息,我的测试失败了。
这是我正在使用的代码示例:
package com.example.app.android;
import okhttp3.ResponseBody;
import okhttp3.OkHttpClient;
import java.util.concurrent.TimeUnit;
import java.io.IOException;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import android.util.Log;
public class Retrofit2Requests extends BasicRequest
{
private Call<ResponseBody> call;
private OkHttpClient _client;
private String _baseUrl;
private Retrofit2Adapter _adapter;
private static final String LOG_TAG = "RetroFit2Requests";
public Retrofit2Requests (String baseUrl) throws Exception
{
_client = new OkHttpClient
.Builder()
.connectTimeout(TIME_SOCKET_TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(TIME_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
.build();
_adapter = (Retrofit2Adapter) new Retrofit.Builder()
.client(_client)
.baseUrl(baseUrl)
.build()
.create(Retrofit2Adapter.class);
_baseUrl = baseUrl;
}
public void getResponse(String data) throws IOException
{
Call<ResponseBody> call = _adapter.getDelayResponse(50, data);
call.enqueue(getCallback());
}
private Callback getCallback()
{
return new Callback<ResponseBody>()
{
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response)
{
ResponseBody responseBody = (ResponseBody) response.body();
Log.d(LOG_TAG, "ResponseBody: " + responseBody.toString());
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t)
{
Log.e(LOG_TAG, "An exception occured fetchign response...", t);
}
};
}
}
此代码的目标不是测试任何业务逻辑或我的应用程序中的任何特殊内容。 它应该做的就是尝试一个请求,就是这样。
这也是我的 Gradle 依赖项。 基于./gradlew :app:dependencies
的输出,我也清除了关于同一地方不同版本改造的任何潜在问题。 该应用程序不使用混淆或缩小,因为它再次只应该执行网络请求。
dependencies {
compile 'org.apache.httpcomponents:httpclient-android:4.3.5.1'
compile 'com.mcxiaoke.volley:library:1.0.19'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile 'org.apache.commons:commons-lang3:3.7'
compile 'com.squareup.retrofit2:retrofit:2.4.0'
compile 'com.android.support:multidex:1.0.1'
androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'junit:junit:4.12'
}
如果你很好奇,是的,我正在对多个网络库做同样的事情。 它们的存在除非创建这个构建 NoClassDefFoundException 应该无关紧要。 以前,我也明确地直接依赖 OkHttp,但由于 Retrofit2 依赖于它,我自然而然地跳过了该依赖项。
这是我的 android 应用程序的 defaultConfig:
defaultConfig {
applicationId 'com.example.app.android'
minSdkVersion 16
targetSdkVersion 24
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
dexOptions {
preDexLibraries true
javaMaxHeapSize '6g'
incremental true
}
}
通过反编译调试APK,我能够看到retrofit2/Retrofit.class 不可用。 这令人困惑,因为根据我的理解,Dex'ing 不应该影响它。
任何想法可能是这个问题的根源并在这种情况下解决?
NoClassDefFoundError
错误意味着找不到类的定义。 它与NoClassFoundException
不同。
NoClassDefFoundError
: JVM 可以找到类,但无法成功加载它。(初始化类时出错)
NoClassFoundException
: JVM 在类路径中找不到类。
NoClassDefFoundError
总是在类初始化期间发生。 我建议你清理项目并检查Lretrofit2/Retrofit$Builder
的初始化过程
希望这篇文章可以帮助你了解 Java 的 NoClassDefFoundError
就我而言,我只是清理并重建项目,这让我解决了这个问题。 当您更改任何类名但编译器仍将先前的类名保留在缓存中并且在运行时编译器无法找到先前存储的类名时,会出现此异常,因为您稍后更改了名称。
将此添加到您的应用程序的 build.gradle 中,在 android {...} 中:
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
然后清理并重建您的项目。 它对我有用。
这个问题在 Retrofit 2.8.1 中得到解决,如果它低于 2.8.1,只需将改造依赖升级到 2.8.1。
从改造变更日志:
版本 2.8.1 (2020-03-25) 修复:不访问 MethodHandles。 在 Android API 24 和 25 上查找。该类仅在 Android API 26 及更高版本上可用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.