java.lang.NoClassDefFoundError:com.example.api.retrofit.AuthenticationInterceptor $ intercept $ 1

时间:2017-09-29 09:57:55

标签: android kotlin retrofit2 interceptor okhttp3

我最近在我的应用中添加了retrofit2。它在运行Android 8.0的Nexus 6P上运行良好,但是在运行Android 6.0.1的旧版OnePlus One上进行测试时,我遇到了错误:

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);
    }
}

2 个答案:

答案 0 :(得分:1)

尝试禁用即时运行。

1 2 3

答案 1 :(得分:1)

经过几个小时的调试后,我弄清楚发生了什么:

在我的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 was added in API level 24。 这就是它在Android 8.0(API级别26)上运行的原因,并且它在Android 6.0.1(API级别23)上无效。

所以,我最终使用了常规for循环,而不是我最初使用的forEach。

这里的主要问题是例外:java.lang.NoClassDefFoundError: com.example.api.retrofit.AuthenticationInterceptor$intercept$1。如果它会说java.lang.NoClassDefFoundError: java.util.function.BiConsumer,我认为调试会容易得多。