以往為了檢查 API 呼叫的 Request 或 Response 是否正確,都是土法煉鋼式的自行加註 Log
。後來改用 Retrofit 之後,發現要加 Log
變得好麻煩,這才發現原來有 HttpLoggingInterceptor
可以自動印 Log 。
💡 OkHttp 的 Interceptors 介面有許多實作的類別,可以針對 API 呼叫做很多不一樣的事情,有興趣的讀者可以多利用這個關鍵字下去尋找相關的資料,本篇文章就不贅述。
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'
📢 注意! 套件引用的版本,請以官方最新版本為準。
HttpLoggingInterceptor
到 OkHttpClient
private fun getOkHttpClient(): OkHttpClient {
val loggingInterceptor: HttpLoggingInterceptor =
HttpLoggingInterceptor().setLevel(
if (BuildConfig.DEBUG) {
// Debug 模式下才開啟
HttpLoggingInterceptor.Level.BODY
} else {
HttpLoggingInterceptor.Level.NONE
}
)
return OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
// ...
.build()
}
什麼都不印
--> POST /greeting http/1.1 (3-byte body)
<-- 200 OK (22ms, 6-byte body)
印 Request 跟 Response 的 Header。
--> POST /greeting http/1.1
Host: example.com
Content-Type: plain/text
Content-Length: 3
--> END POST
<-- 200 OK (22ms)
Content-Type: plain/text
Content-Length: 6
<-- END HTTP
Body & Header 全部都印
--> POST /greeting http/1.1
Host: example.com
Content-Type: plain/text
Content-Length: 3
Hi?
--> END POST
<-- 200 OK (22ms)
Content-Type: plain/text
Content-Length: 6
Hello!
<-- END HTTP
公司專案中有一個需要上傳 01:30 長度的影片,檔案大小約 25MB。之前測試上傳都沒有問題,但在某測試版本中加上 HttpLoggingInterceptor
後,只要有影片的上傳都會閃退。
查詢 Firebase 與重現的錯誤都出現一樣的 OutOfMemoryError
:
Fatal Exception: java.lang.OutOfMemoryError: Failed to allocate a 88561088 byte allocation with 25165824 free bytes and 69MB until OOM, target footprint 220477624, growth limit 268435456
at okio.Buffer.readByteArray(Buffer.kt:1429)
at okio.Buffer.readString(Buffer.kt:306)
at okio.Buffer.readString(Buffer.kt:295)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.kt:209)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at com.tms.qpass.data.remote.TokenInterceptor.intercept(TokenInterceptor.kt:43)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:517)
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:923)
經查測後發現與 StackOverflow 上的這篇 Upload large video file use Retrofit(Android) have OutOfMemoryError 相符。
既然問題是出在
HttpLoggingInterceptor
所產生的OutOfMemoryError
,那其實不一定要像 StackOverflow 上說的改成Level.NONE
,只要不是設定Level.BODY
都可以。調整設定後確定可以正常上傳。🤗
本文同步發布在 HackMD