SharedPreference(下文简称sp)是一种轻量级的存储方式,是它的设计所决定的:sp在创建的时候会把整个文件全部加载进内存,如果你的sp文件比较大,那么会带来几个严重问题:
第一次从sp中获取值的时候,有可能阻塞主线程,使界面卡顿、掉帧。
解析sp的时候会产生大量的临时对象,导致频繁GC,引起界面卡顿。
这些key和value会永远存在于内存之中,占用大量内存。
子线程从文件中加载xml文件
private void startLoadFromDisk() {
synchronized (mLock) {
mLoaded = false;
}
new Thread("SharedPreferencesImpl-load") {
public void run() {
loadFromDisk();
}
}.start();
}
getString 方法 在子线程中获取完之后, 在通知获取
public String getString(String key, @Nullable String defValue) {
synchronized (mLock) {
awaitLoadedLocked();
String v = (String)mMap.get(key);
return v != null ? v : defValue;
}
}
private void awaitLoadedLocked() {
if (!mLoaded) {
// Raise an explicit StrictMode onReadFromDisk for this
// thread, since the real read will be in a different
// thread and otherwise ignored by StrictMode.
BlockGuard.getThreadPolicy().onReadFromDisk();
}
while (!mLoaded) {
try {
mLock.wait();
} catch (InterruptedException unused) {
}
}
if (mThrowable != null) {
throw new IllegalStateException(mThrowable);
}
}
加载进入的大对象会保存在 内存中, ContextImpl#getSharedPreference 中保存缓存
JSON或者HTML格式存放在sp里面的时候,需要转义,这样会带来很多 & 这种特殊符号,sp在解析碰到这个特殊符号的时候会进行特殊的处理,引发额外的字符串拼接以及函数调用开销
每次edit都会创建一个Editor对象,额外占用内存;当然多创建几个对象也影响不了多少;但是,多次apply可能会卡界面