您好,登錄后才能下訂單哦!
OkHttp是可以說是Android開發中,每個項目都必需依賴的網絡庫,我們可以很便捷高效的處理網絡請求,極大的提升了編碼效率。但是有時候,我們使用OkHttp也會遇到這樣的問題
一.崩潰的stacktrace
E AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher E AndroidRuntime: Process: com.example.okhttpexceptionsample, PID: 13564 E AndroidRuntime: java.lang.NullPointerException: blablabla E AndroidRuntime: at com.example.okhttpexceptionsample.MainActivity$createNPEInterceptor$1.intercept(MainActivity.kt:61) E AndroidRuntime: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112) E AndroidRuntime: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87) E AndroidRuntime: at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.kt:184) E AndroidRuntime: at okhttp3.RealCall$AsyncCall.run(RealCall.kt:136) E AndroidRuntime: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) E AndroidRuntime: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) E AndroidRuntime: at java.lang.Thread.run(Thread.java:784)
二.為什么會崩潰
從上面的stacktrace,我們可以分析到,發生了NullPointerException。發生了崩潰。
等等,我記得OkHttp有處理異常的情況呢。
嗯,確實,OkHttp有處理異常的情況,比如發生異常會調用onFailure
。比如下面的Callback的內容介紹。
interface Callback {
/**
* Called when the request could not be executed due to cancellation, a connectivity problem or
* timeout. Because networks can fail during an exchange, it is possible that the remote server
* accepted the request before the failure.
*/
fun onFailure(call: Call, e: IOException)
/**
* Called when the HTTP response was successfully returned by the remote server. The callback may
* proceed to read the response body with [Response.body]. The response is still live until its
* response body is [closed][ResponseBody]. The recipient of the callback may consume the response
* body on another thread.
*
* Note that transport-layer success (receiving a HTTP response code, headers and body) does not
* necessarily indicate application-layer success: `response` may still indicate an unhappy HTTP
* response code like 404 or 500.
*/
@Throws(IOException::class)
fun onResponse(call: Call, response: Response)
}
是的.
所以沒有被處理,發生了崩潰。
那么有沒有辦法解決,讓這種崩潰不發生,對用戶不進行干擾呢?其實是可以的。
package com.example.okhttpexceptionsample
import okhttp3.Interceptor
import okhttp3.Response
import java.io.IOException
/**
* 對于Interceptor的intercept中可能出現的Throwable包裹成IOExceptionWrapper,轉成網絡請求失敗,而不是應用崩潰
*/
class SafeGuardInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
try {
return chain.proceed(chain.request())
} catch (t: Throwable) {
throw IOExceptionWrapper("SafeGuarded when requesting ${chain.request().url}", t)
}
}
}
/**
* 將chain.proceed處理中發生的Throwable包裝成IOExceptionWrapper
*/
class IOExceptionWrapper(message: String?, cause: Throwable?) : IOException(message, cause)
上面的代碼,我們將任何Throwable
的轉成IOExceptionWrapper
(偽裝成IOException),然后添加到OkHttpClient中
fun createOKHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(SafeGuardInterceptor())
.build()
}
當我們再次執行有NPE的代碼,日志就發生了改變(不再是崩潰的日志,而是異常的日志)
W System.err: com.example.okhttpexceptionsample.IOExceptionWrapper: SafeGuarded=blablabla
W System.err: at com.example.okhttpexceptionsample.SafeGuardInterceptor.intercept(SafeGuardInterceptor.kt:12)
W System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
W System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
W System.err: at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.kt:184)
W System.err: at okhttp3.RealCall$AsyncCall.run(RealCall.kt:136)
W System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
W System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
W System.err: at java.lang.Thread.run(Thread.java:784)
W System.err: Caused by: java.lang.NullPointerException: blablabla
W System.err: at com.example.okhttpexceptionsample.MainActivity$createNPEInterceptor$1.intercept(MainActivity.kt:61)
W System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
W System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
W System.err: at com.example.okhttpexceptionsample.SafeGuardInterceptor.intercept(SafeGuardInterceptor.kt:10)
W System.err: ... 7 more
上述需要注意兩點
這么做,當然可以明顯增強請求的穩定性和應用的崩潰率。但是是不是也有一些問題呢?比如
在軟件工程中,很多決定都是trade-off的體現,具體的實施方案大家可以自行平衡選擇。
更多Android高級面試合集放在github上面了
,需要的小伙伴可以點擊關于我?聯系我獲取
非常希望和大家一起交流 , 共同進步
目前是一名程序員,不僅分享 Android開發相關知識,同時還分享技術人成長歷程,包括個人總結,職場經驗,面試經驗等,希望能讓你少走一點彎路。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。