我最近在我的应用中添加了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);
}
}
答案 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
,我认为调试会容易得多。