java.lang.NoClassDefFoundError:解析失败:Lretrofit2 / Retrofit $ Builder;

时间:2018-06-05 10:02:55

标签: java android retrofit retrofit2 dex

我正致力于在Android中编写非常简单的基于Retrofit2的仪器化测试(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依赖项。根据{{​​1}}的输出,我也在同一个地方解决了有关不同版本改造的任何潜在问题。该应用程序不使用混淆或缩小,因为它再次只应该进行网络请求。

./gradlew :app:dependencies

如果您有点好奇,是的,我在使用多个网络库做同样的事情。它们的存在除非创建这个构建NoClassDefFoundException应该无关紧要。以前,我也明确地依赖OkHttp,但由于retrofit2依赖于它,我自然会跳过这种依赖。

这是我的Android应用程序的defaultConfig:

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'
}

通过反编译调试APK,我能够看到retrofit2 / Retrofit.class不可用。这是令人困惑的,因为我的理解是Dex不应该影响它。

任何想法可能是这个问题的根源并在此背景下解决?

提前致谢,

安德烈亚斯。

4 个答案:

答案 0 :(得分:0)

NoClassDefFoundError错误意味着找不到类的定义。它与NoClassFoundException不同。

  • NoClassDefFoundError:JVM可以找到类,但无法加载它成功。(初始化类时出错)

  • NoClassFoundException:JVM无法在类路径中找到该类。

NoClassDefFoundError总是在初始化阶段发生。我建议你清理项目并检查Lretrofit2/Retrofit$Builder

的初始化过程

希望这篇文章可以帮助你Java understand NoClassDefFoundError

答案 1 :(得分:0)

就我而言,我只是清理并重建项目,这使我解决了这个问题。当您更改任何类名,但编译器仍将先前的类名保留在缓存中时,在运行时,当您稍后更改名称时,编译器将找不到先前存储的类名。

答案 2 :(得分:0)

将其添加到android {...}中的应用的build.gradle中:

compileOptions {
    sourceCompatibility 1.8
    targetCompatibility 1.8
}

然后清理并重建项目。它对我有用。

答案 3 :(得分:0)

在Retrofit 2.8.1中解决了该问题,只要将其升级到2.8.1以下就可以了。

从翻新changelog

版本2.8.1(2020-03-25) 修复:不要访问MethodHandles。在Android API 24和25上查找。该类仅 在Android API 26及更高版本上可用。