DataStore —— SharedPreferences 的替代者 ?

瞎逛的時候發現了一個新東西,來和大家分享一下。

SharedPreferences 大家應該都用過,它的槽點很多,多到我專門寫了一篇文章。

細數 SharedPreferences 的那些槽點 !

不過,官方吐槽,最爲致命

  1. Synchronous API encourages StrictMode violations

  2. apply() and commit() have no mechanism of signalling errors

  3. apply() will block the UI thread on fsync()

  4. Not durable – it can returns state that is not yet persisted

  5. No consistency or transactional semantics

  6. Throws runtime exception on parsing errors

  7. Exposes mutable references to its internal state

我就不翻譯了,可能會翻的不是很準確。以上吐槽來自 AndroidX 添加的新成員 DataStore 的類註釋,地址如下:

https://cs.android.com/androidx/platform/frameworks/support/+/androidx-master-dev:datastore/datastore-core/src/main/kotlin/androidx/datastore/DataStore.kt

什麼是 DataStore ?

那麼,什麼是 DataStore 呢?

DataStore provides a safe and durable way to store small amounts of data, such as preferences and application state. It does not support partial updates: if any field is modified, the whole object will be serialized and persisted to disk. If you want partial updates, consider the Room API (SQLite).

DataStore provides ACID guarantees. It is thread-safe, and non-blocking. In particular, it addresses these design shortcomings of the SharedPreferences API。

這個我可以翻譯一下。

DataStore 提供了一種存儲輕量數據的安全穩定的方案,例如配置文件,應用狀態等。它不支持局部更新:如果任何一個成員變量被修改了,整個對象都將被序列化並持久化到磁盤。對於局部修改,請考慮使用 Room 。

DataStore 保證原子性,一致性,隔離性,持久性。它是線程安全,且非阻塞的。尤其是,它解決了 SharedPreferences API 的設計缺陷。

好傢伙,看起來這就是 SharedPreferences 的替代品了。

上代碼

簡單看一下代碼實現。

DataStore 是一個接口。

interface DataStore<T> {
 
    val dataFlow: Flow<T>


    suspend fun updateData(transform: suspend (t: T) -> T): T

  
    interface Serializer<T> {

        fun readFrom(input: InputStream): T

        fun writeTo(t: T, output: OutputStream)

        val defaultValue: T
    }

    // TODO(b/151635324): Add initializers.
    // TODO(b/151635324): Add exception handlers.
    // TODO(b/151635324): Consider adding snapshot API.
}

沒錯,是基於 協程Flow 實現的。

  • dataFlow 是一個 Flow 對象

  • updateData() 用於更新對象

  • Serializer 接口,提供序列化和持久化能力

目前源碼中僅僅提供了一個實現類:SingleProcessDataStore 。從名字就可以看出來,不支持多進程。看一下其中幾個關鍵方法。

class SingleProcessDataStore<T>(
    private val produceFile: () -> File,
    private val serializer: DataStore.Serializer<T>,
    private val scope: CoroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
) : DataStore<T> {
    ......
    private suspend fun readData(): T {
        // TODO(b/151635324): consider caching produceFile result.
        val file = produceFile()
        try {
            FileInputStream(file).use { stream ->
                return serializer.readFrom(stream)
            }
        } catch (ex: FileNotFoundException) {
            if (file.exists()) {
                throw ex
            }
            return serializer.defaultValue
        }
    }
    
    private fun writeData(newData: T) {
        // TODO(b/151635324): consider caching produceFile result.
        val file = produceFile()
        file.mkdirs()
        val scratchFile = File(file.absolutePath + SCRATCH_SUFFIX)
        try {
            FileOutputStream(scratchFile).use { stream ->
                serializer.writeTo(newData, stream)
                stream.fd.sync()
                // TODO(b/151635324): fsync the directory, otherwise a badly timed crash could
                //  result in reverting to a przuihouevious state.
            }
            scratchFile.renameTo(file)
        } catch (ex: IOException) {
            if (scratchFile.exists()) {
                scratchFile.delete()
            }
            throw ex
        }
    }
    ......
}

readData()writeData() 實際都是在讀寫文件。

具體用法詳見官方寫的單元測試 SingleProcessDataStoreTest,地址如下:

https://cs.android.com/androidx/platform/frameworks/support/+/androidx-master-dev:datastore/datastore-core/src/test/kotlin/androidx/datastore/SingleProcessDataStoreTest.kt

最後

到目前爲止,DataStore 仍在開發中,並沒有發佈過任何可用的版本 ,現在並不足以替代 SharedPreferences 。按 Google 的尿性,哪天流產了其實也不足爲奇。你可以在 androidx-master-dev 中持續關注。

不過兩個問題是可以確定的。

第一,Google 自己也快看不下去 SharedPreferences 了。

第二,越來越多的新特性都是基於 Kotlin 實現的了,甚至只對 Kotlin 提供支持,大有 Kotlin First 到 Kotlin Only 的趨勢。

所以,還沒有學習 Kotlin 的同學們,抓緊上車吧!


今天的文章就到這裏了,我是一直堅持原創的秉心說,更多最新 Android 動態,掃碼關注我的公衆號吧 !

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章