android - 应用程序在获取数据时崩溃并在 Logcat 中显示中断异常
问题描述
我是 Kotlin MVVM 的新手,我使用 Executor 的概念来创建一个线程池来获取 Endpoint 的资源,但我不断收到异常,最终导致应用程序崩溃。
崩溃日志:
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 的代码基于 Retrofit
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)
}
}
而且我正在尝试观察由于异常的第一个错误而导致的 null 配方
recipeListViewModel?.getRecipes()?.observe(this, { recipe ->
mAdapter?.setRecipes(recipe)
})
解决方案
这是由于超时。您需要扩展 API 请求和响应的时间。
推荐阅读
- python - Django CreateView 多对象插入
- swift - 尝试进行涉及 web 视图的 UI 测试时 Xcode 崩溃
- c# - 表名和实体框架6的关系是怎么做的?
- javascript - 如何使用 Cypress io 将功能文件与步骤定义链接起来
- c# - 如何将一串 0 和 1 转换为布尔数组
- python - 当我输入时,它说无效选项
- python - 使用 Python Bottle 生成物品不起作用
- c++ - boost::filesystem::create_directory 抛出了 boost::filesystem::filesystem_error: Bad address
- android - 从抽屉中调用活动时应用程序关闭
- r - 导入具有多种记录类型的文件