無痛處理狀態儲存 — Jetpack Savestate Library

前言

狀態儲存在 Android 開發上一直是很重要的一環,不管是旋轉螢幕還是畫面被 system 回收,都需要把資料完好的填補回去才能確保有好的使用者體驗。

以往若要實作狀態儲存,大概免不了下面這些 code,因為 ViewModel 不知道 Activity 的狀態儲存週期,所以我們必須要告訴 ViewModel 什麼時候需要儲存狀態。

今天想跟大家分享的是 Jetpack 的一個輕量 Library — Savedstate,它能讓我們更方便且乾淨的處理狀態儲存!另外如果有在使用的 Android Architecture ViewModel 的朋友們,也有專為 ViewModel 設計的 Savedstate library 可以用,背後的原理是差不多的。

正文

SavedStateRegistry

這是我們主要需要互動的 class,可以看到常使用的 ComponentActivity 和 Fragment 都實作了 SavedStateRegistryOwner,所以換句話說只要是繼承他們的畫面,我們都能直接拿到 SavedStateRegistry。

接下來就來看看這個 class 到底怎麼使用吧!

註冊(registerSavedStateProvider)

首先是註冊當狀態需要被儲存的時候,我們需要儲存一些什麼資訊?

這邊需要提供 key 以便 restore 時讀取,而 SavedStateProvider 則是提供 state bundle 的 interface,假如我們想要在 configuration change 的時候儲存 custom view 的資訊,可以這樣寫 👇

registry.registerSavedStateProvider(VIEW_STATE) {
bundleOf("enable" to view.enabled)
}

讀取(consumeRestoredStateForKey)

接著當 Activity 進行 onRestoreInstanceState 之後,我們就可以從 SavedStateRegistry 拿到我們儲存的資訊了!

val bundle = registry.consumeRestoredStateForKey(VIEW_STATE)
val enabled = bundle?.getBoolean("enable")

但問題是,我們該怎麼知道 Activity 已經重新生成了呢?

這邊建議大家可以搭配著 Lifecycle 做使用,我們可以在 Lifecycle 的 create 狀態讀取看看有沒有需要 restore 的資料。

整合!

講解完使用方式之後我們就來整合吧,看看到底跟以往的方式有什麼差別

有了 SavedStateRegistry 之後,我們不需要再從 Activity 告知 ViewModel 該做些什麼事情,code 也變得簡潔好懂了 🎉

Tips:這邊記得要保護一下 consumeRestoredStateForKey 這個 function,如果在 onCreate 之前就讀取 state 的話會收到 IllegalStateException

小結

前陣子幫公司導入這個輕量級 Library,但發現網路上連英文的資訊量都還很少,更別說中文了。所以就花了點時間啃了 source code 釐清一下頭緒,順便整理成短文供大家參考,真的算是滿方便的一個 Library,幫你把狀態儲存的週期都包裝好了 👍

目前小弟正在努力學習 Android 相關技術,偶爾會寫寫文章練練文筆,有錯誤或是能改進的地方都歡迎大大們留言指教!

最後,希望這篇文章能幫助到需要的開發者們,謝謝大家 🙌

--

--

邱懷民
一個被音樂耽誤的Android工程師

喜歡抱著吉他彈彈唱唱,夢想是靠著寫程式改變世界。