在 Android 開發中,我們常使用 Kotlin 的 use {}
語法來自動管理資源,例如關閉檔案、關閉資料庫 Cursor。但這個便利的語法在 Android 11 以下,對某些類別其實會出錯造成應用程式閃退。如果一時不查,小心這坑就這樣踩了下去…
錯誤說明
|
|
這段程式碼在 Android 12(API 31)以上沒問題,但在 Android 11 (API 30) 以下執行時,會拋出以下錯誤:
|
|
白話來說,上面這個錯誤告訴我們,TypedArray
並沒有實作 AutoCloseable
介面,所以在試圖呼叫 AutoCloseable.close()
時拋出 IncompatibleClassChangeError
錯誤。
問題釐清:use {}
的背後原理
Kotlin use {}
是一個 extension function,會在 Block 結束後自動呼叫 AutoCloseable.close()
方法來釋放資源。
|
|
但在 Android 11 (API 30) 以下的版本,TypedArray
並沒有實作 AutoCloseable
,也就是說它根本不支援 close()
方法,導致執行期間會嘗試呼叫一個不存在的方法,最後拋出錯誤導致 App 閃退。
正確做法:使用 AndroidX 的 use {}
改用 androidx.core.content.res.use
,而它的實作方式如下:
|
|
跟 Kotlin 版相比, androidx.core.content.res.use
是用 recycle()
來釋放資源,不會去呼叫那個不存在的 AutoCloseable.close()
。
結論,如果你遇到這個問題,請記得將 import androidx.core.content.res.use
補上,就沒問題了。
延伸補充與建議
Kotlin 的 use
有兩種實作來源:
在開發時建議檢查類別是否有實作 AutoCloseable
或 Closeable
。
如果有實作就可以安心使用 Kotlin 的 use {}
。
否則請改用 AndroidX 提供的 use {}
方法,或者手動呼叫 recycle()
或 close()
釋放資源。
舉例:android.database.Cursor
就有實作 Closeable
,所以可以使用 Kotlin 的 use {}
。
以上就是本次的踩坑筆記分享,希望能幫到你的忙,或是至少能幫到未來的我自己!?🤯
下個坑見 🤪