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

Android 应用程序在获取数据时崩溃,并在Logcat中显示中断的异常,android,kotlin,retrofit2,Android,Kotlin,Retrofit2,我是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.ja

我是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)
        }

    }

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

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

问题是
mRecipes?.postValue(null)
用于非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
        }

    }
private class retrieverecperunable(private val query:String,private val pageNumber:Int):可运行{
var cancelRequest=false
覆盖趣味跑(){
试一试{
val response=getRecipes(查询,页码)?.execute()
如果(取消请求){
返回
}
如果(响应?.code()==200){
val list:MutableList=ArrayList((响应?.body()作为RecipeSearchResponse.recipes)
如果(页码==1){
mRecipes?.postValue(列表)
}否则{
val currentRecipe:MutableList=mRecipes?。值为MutableList
currentRecipe.addAll(列表)
mRecipes?.postValue(当前配方)
}
}否则{
val错误:字符串=响应?.errorBody().toString()
Log.i(“标记”,“运行:$error”)
mRecipes?.postValue(emptyList())//此行
}
}捕获(例如:IOException){
Log.e(“标记”,“运行:”,ex)
mRecipes?.postValue(emptyList())//此行
}
}

对于非空接收,问题是
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
        }

    }
private class retrieverecperunable(private val query:String,private val pageNumber:Int):可运行{
var cancelRequest=false
覆盖趣味跑(){
试一试{
val response=getRecipes(查询,页码)?.execute()
如果(取消请求){
返回
}
如果(响应?.code()==200){
val list:MutableList=ArrayList((响应?.body()作为RecipeSearchResponse.recipes)
如果(页码==1){
mRecipes?.postValue(列表)
}否则{
val currentRecipe:MutableList=mRecipes?。值为MutableList
currentRecipe.addAll(列表)
mRecipes?.postValue(当前配方)
}
}否则{
val错误:字符串=响应?.errorBody().toString()
Log.i(“标记”,“运行:$error”)
mRecipes?.postValue(emptyList())//此行
}
}捕获(例如:IOException){
Log.e(“标记”,“运行:”,ex)
mRecipes?.postValue(emptyList())//此行
}
}

我会试试看。!!我会试试看!!