簡體   English   中英

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

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM