应用程序在获取数据时崩溃,并在Logcat中显示中断异常



我是Kotlin MVVM的新手,我使用Executor的概念创建了一个线程池来获取端点的资源,但我不断地遇到异常,最终导致应用程序崩溃。

故障日志:

2020-11-12 11:43:39.768 3018-3043/com.ankittlabs.rasodarecipe E/TAG: run: 
java.io.InterruptedIOException: interrupted
at okio.Timeout.throwIfReached(Timeout.java:146)
at okio.Okio$1.write(Okio.java:76)
at okio.AsyncTimeout$1.write(AsyncTimeout.java:180)
at okio.RealBufferedSink.flush(RealBufferedSink.java:224)
at okhttp3.internal.http1.Http1ExchangeCodec.finishRequest(Http1ExchangeCodec.java:190)
at okhttp3.internal.connection.Exchange.finishRequest(Exchange.java:101)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:86)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:43)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:94)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:88)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:229)
at okhttp3.RealCall.execute(RealCall.java:81)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:204)
at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall.execute(DefaultCallAdapterFactory.java:108)
at com.ankittlabs.rasodarecipe.request.RecipeApiClient$RetrieveRecipeRunnable.run(RecipeApiClient.kt:37)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:458)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
2020-11-12 11:43:39.769 3018-3018/com.ankittlabs.rasodarecipe D/AndroidRuntime: Shutting down VM


--------- beginning of crash
2020-11-12 11:43:39.770 3018-3018/com.ankittlabs.rasodarecipe E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.ankittlabs.rasodarecipe, PID: 3018
java.lang.NullPointerException: recipe must not be null
at com.ankittlabs.rasodarecipe.RecipeActivity$subscribeObserver$1.onChanged(RecipeListActivity.kt:48)
at com.ankittlabs.rasodarecipe.RecipeActivity$subscribeObserver$1.onChanged(RecipeListActivity.kt:26)
at androidx.lifecycle.LiveData.considerNotify(LiveData.java:131)
at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:149)
at androidx.lifecycle.LiveData.setValue(LiveData.java:307)
at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:50)
at androidx.lifecycle.LiveData$1.run(LiveData.java:91)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2020-11-12 11:43:39.777 3018-3018/com.ankittlabs.rasodarecipe I/Process: Sending signal. PID: 3018 SIG: 9

获取API的代码基于改装

private class RetrieveRecipeRunnable(private val query: String, private val pageNumber: Int) : Runnable {
var cancelRequest = false
override fun run() {
try {
val response = getRecipes(query, pageNumber)?.execute()
if (cancelRequest) {
return
}
if (response?.code() == 200) {
val list: MutableList<Recipe> = ArrayList((response?.body() as RecipeSearchResponse).recipes)
if (pageNumber == 1) {
mRecipes?.postValue(list)
} else {
val currentRecipe: MutableList<Recipe> = mRecipes?.value as MutableList<Recipe>
currentRecipe.addAll(list)
mRecipes?.postValue(currentRecipe)
}
} else {
val error: String = response?.errorBody().toString()
Log.i("TAG", "run: $error")
mRecipes?.postValue(null)
}
} catch (ex: IOException) {
Log.e("TAG", "run: ", ex)
mRecipes?.postValue(null)
}
}

我正在尝试观察由于异常的第一个错误而导致的无效配方

recipeListViewModel?.getRecipes()?.observe(this, { recipe ->
mAdapter?.setRecipes(recipe)
})

由于超时。您需要延长API请求和响应的时间。

问题是非空接收器的mRecipes?.postValue(null)。只需使用mRecipes?.postValue(emptyList())而不是mRecipes?.postValue(null)

应该是:

private class RetrieveRecipeRunnable(private val query: String, private val pageNumber: Int) : Runnable {
var cancelRequest = false
override fun run() {
try {
val response = getRecipes(query, pageNumber)?.execute()
if (cancelRequest) {
return
}
if (response?.code() == 200) {
val list: MutableList<Recipe> = ArrayList((response?.body() as RecipeSearchResponse).recipes)
if (pageNumber == 1) {
mRecipes?.postValue(list)
} else {
val currentRecipe: MutableList<Recipe> = mRecipes?.value as MutableList<Recipe>
currentRecipe.addAll(list)
mRecipes?.postValue(currentRecipe)
}
} else {
val error: String = response?.errorBody().toString()
Log.i("TAG", "run: $error")
mRecipes?.postValue(emptyList()) //this line
}
} catch (ex: IOException) {
Log.e("TAG", "run: ", ex)
mRecipes?.postValue(emptyList())//this line
}
}

最新更新