java.lang.NoClassDefFoundError: com.example.api.retrofit.AuthenticationInterceptor $ перехват $ 1

Недавно я добавил retrofit2 в свое приложение. Он хорошо работает на Nexus 6P под управлением Android 8.0, но при тестировании на старом OnePlus One, работающем под управлением Android 6.0.1, я столкнулся с ошибкой:

java.lang.NoClassDefFoundError: com.example.api.retrofit.AuthenticationInterceptor$intercept$1 at com.example.api.retrofit.AuthenticationInterceptor.intercept(AuthenticationInterceptor.kt:21) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67) at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:185) at okhttp3.RealCall.execute(RealCall.java:69) at retrofit2.OkHttpCall.execute(OkHttpCall.java:180) at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.execute(ExecutorCallAdapterFactory.java:91) at com.example.fragment.xx.XXFragment$onViewCreated$2.getItemsForConstraint(XXFragment.kt:53) at com.example.view.MyAutoCompleteTextView$Adapter$getFilter$1.performFiltering(MyAutoCompleteTextView.kt:114) at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.os.HandlerThread.run(HandlerThread.java:61) 

Вот мой код:

build.gradle

 buildscript { ext { okhttpVersion = '3.8.0' retrofitVersion = '2.3.0' } ... } 

Приложение / build.gradle:

 compile "com.squareup.okhttp3:okhttp:$okhttpVersion" compile "com.squareup.okhttp3:logging-interceptor:$okhttpVersion" compile 'com.google.code.gson:gson:2.8.1' compile("com.squareup.retrofit2:retrofit:$retrofitVersion") { exclude module: 'okhttp' } compile "com.squareup.retrofit2:converter-gson:$retrofitVersion" 

Построение сервиса:

 OkHttpClient client = new OkHttpClient().newBuilder() .addInterceptor(new AuthenticationInterceptor(ctx)) .addInterceptor(new HttpLoggingInterceptor() .setLevel(HttpLoggingInterceptor.Level.BODY)) .build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(HOST + VERSION + "/") .client(client) .addConverterFactory(new EnvelopingConverter()) .addConverterFactory(GsonConverterFactory.create()) .build(); retrofitService = retrofit.create(ApiService.class); 

Перехватчик:

 import android.content.Context import com.example.api.Api import com.example.controller.AuthManager import okhttp3.Interceptor import okhttp3.Response class AuthenticationInterceptor(val context: Context) : Interceptor { override fun intercept(chain: Interceptor.Chain?): Response? { var request = chain?.request() val headers = AuthManager.getAuthHeaders(context) if (request != null) { val requestBuilder = request.newBuilder() requestBuilder.addHeader(Api.HEADER_ACCEPT, Api.HEADER_APP_JSON) headers.forEach { key, value -> // this is line 21 requestBuilder.addHeader(key, value) } request = requestBuilder.build() } return chain?.proceed(request) } } 

Я не уверен, в чем проблема? У кого-нибудь есть идеи?

ОБНОВИТЬ:

Написал перехватчик в java и, похоже, работает. Зачем? Я бы очень хотел придерживаться Kotlin для этого проекта.

 public class AuthInterceptor implements Interceptor { private Context context; public AuthInterceptor(Context ctx) { context = ctx; } @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Map<String, String> headers = AuthManager.getAuthHeaders(context); if (request != null) { Request.Builder requestBuilder = request.newBuilder(); requestBuilder.addHeader(Api.HEADER_ACCEPT, Api.HEADER_APP_JSON); for (String key : headers.keySet()) { requestBuilder.addHeader(key, headers.get(key)); } request = requestBuilder.build(); } return chain.proceed(request); } } 

Попробуйте отключить Instant Run.

1 2 3

После нескольких часов отладки я понял, что происходит:

В моем файле gradle я также compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"

Из-за этого он позволил мне использовать следующий код:

 headers.forEach { key, value -> // this is line 21 requestBuilder.addHeader(key, value) } 

При декомпиляции и просмотре кода Java это будет выглядеть так:

 e.forEach((BiConsumer)(new BiConsumer() { // $FF: synthetic method // $FF: bridge method public void accept(Object var1, Object var2) { this.accept((String)var1, (String)var2); } public final void accept(String key, String value) { requestBuilder.addHeader(key, value); } })); 

Проблема здесь в том, что класс BiConsumer был добавлен в уровень API 24 . Именно поэтому он работал на Android 8.0 (API-уровень 26), и он не работал на Android 6.0.1 (API-уровень 23).

Итак, я закончил тем, что использовал регулярный цикл для цикла, а не forEach, на который я пошел первоначально.

Основная проблема здесь заключается в исключении: java.lang.NoClassDefFoundError: com.example.api.retrofit.AuthenticationInterceptor$intercept$1 . Если бы он сказал java.lang.NoClassDefFoundError: java.util.function.BiConsumer , я думаю, было бы намного легче отлаживать.

Давайте будем гением компьютера.