SharedPreferences 進(jìn)行的存儲(chǔ)會(huì)導(dǎo)致數(shù)據(jù)丟失?
最近由于需求迭代, K-V 的存儲(chǔ)方式加入了加解密流程, 然后上線(xiàn)后,發(fā)現(xiàn)依賴(lài)于SharedPreferences 進(jìn)行緩存的頁(yè)面,發(fā)生了一些不可思議的報(bào)錯(cuò),仿佛SharedPreferences 沒(méi)有put數(shù)據(jù)到xml中一樣.一開(kāi)始不太相信,后面分析了下,確實(shí)是這樣.
SharedPreferences 的commit 和apply?
commit 是同步提交, apply是異步處理. 為啥有這兩種區(qū)分呢,那是因?yàn)镾haredPreferences 如果用commit 來(lái)存儲(chǔ)數(shù)據(jù),數(shù)據(jù)量針對(duì)大數(shù)據(jù)那種,很容易造成ANR,因?yàn)橐獢?shù)據(jù)落地才能夠進(jìn)行后續(xù)相應(yīng)的操作的話(huà).你可以想象一下. 而用了apply 這種異步的話(huà), apply的原理是開(kāi)多一份xml 來(lái)進(jìn)行讀寫(xiě), 等數(shù)據(jù)真實(shí)落地后,再刪之前舊的那份xml. 那問(wèn)題來(lái)了,既然這個(gè)過(guò)程是異步的,有沒(méi)有可能會(huì)造成數(shù)據(jù)丟失,或者數(shù)據(jù)不準(zhǔn)確呢? 答案是,確實(shí)如此.SharedPreferences 文件的加載使用了異步線(xiàn)程,而且加載線(xiàn)程并沒(méi)有設(shè)置優(yōu)先級(jí)哼审,如果這個(gè)時(shí)候讀取數(shù)據(jù)就需要等待文件加載線(xiàn)程的結(jié)束署隘。這就導(dǎo)致主線(xiàn)程等待低優(yōu)先線(xiàn)程鎖的問(wèn)題府树,比如一個(gè) 100KB 的 SP 文件讀取等待時(shí)間大約需要 50 ~ 100ms皮钠,并且建議大家提前用預(yù)加載啟動(dòng)過(guò)程用到的 SP 文件冀自。而且重要的一點(diǎn),無(wú)論是commit 還是apply ,他在讀寫(xiě)的過(guò)程都是全量寫(xiě)入的.
SharedPreferences 的IO是否安全?
既然SharedPreferences 是要讀寫(xiě)xml來(lái)進(jìn)行數(shù)據(jù)存儲(chǔ)和讀取的,那么這個(gè)IO操作是否安全呢,在java里, IO操作都會(huì)帶上execption 拋出相應(yīng)的IO異常, 關(guān)于SharedPreferences也是一樣的.如圖:所以其中的數(shù)據(jù)讀取量,根據(jù)相應(yīng)的流而議,文件越大,那么相應(yīng)的風(fēng)險(xiǎn)也就越大啦.因此SharedPreferences 也只適合那種輕量級(jí)的數(shù)據(jù)流的讀寫(xiě).
SharedPreferences 在線(xiàn)程間的表現(xiàn)如何?
首先看入?yún)?
方法是線(xiàn)程安全的, 但是跨線(xiàn)程呢? 如果你用了MODE_MULTI_PROCESS 的話(huà),那別的線(xiàn)程就可以更改你的數(shù)據(jù)啦.但是如果你不用這種方式的話(huà), 那數(shù)據(jù)就不能給到別的線(xiàn)程去讀寫(xiě),因此,這個(gè)流程,大家可以腦補(bǔ)一下.
那么如何處理呢?
1.不用用SharedPreferences 保存跳轉(zhuǎn)入口的緩存,而應(yīng)該利用Intent 去傳遞相應(yīng)數(shù)據(jù)到Activity 或者Fragment.
2.不要存儲(chǔ)大數(shù)據(jù), 包括一些加解密,因?yàn)榧用懿僮鲿?huì)導(dǎo)致string 的長(zhǎng)度變大, 如果都是加密存儲(chǔ),那么內(nèi)容可想而知.
3.可以區(qū)分用戶(hù)級(jí)別數(shù)據(jù)和應(yīng)用級(jí)別數(shù)據(jù)來(lái)進(jìn)行處理,如果用戶(hù)數(shù)據(jù)較大, 可以考慮一些開(kāi)源庫(kù)如MMKV,如果較小,需要加密處理保證安全的話(huà),針對(duì)部分字段進(jìn)行加解密即可.
4.應(yīng)用盡量不要過(guò)分依賴(lài)SharedPreferences來(lái)進(jìn)行相應(yīng)的業(yè)務(wù)邏輯處理操作.考慮一些設(shè)計(jì)模式來(lái)避免這個(gè)過(guò)程吧.