1.context.getPreferences (int mode)
获取的是此Activity私有的Preference,以此Activity的名字命名,因此一个Activity只有一个,属于这个Activity。
保存在data/data/包名/shared_prefs位置下
public SharedPreferences getPreferences(int mode) { return getSharedPreferences(getLocalClassName(), mode); }
2.context.getSharedPreferences (String name, int mode)
属于整个应用,可以有多个,以给定的name为文件名保存在系统中。
保存在data/data/包名/shared_prefs位置下
3.PreferenceManager.getDefaultSharedPreferences(context);
属于整个应用,只有一个,根据包名命名("包名"+"_preferences.xml")
其实也是调用
context.getSharedPreferences (String name, int mode)
保存在data/data/包名/shared_prefs位置下
public static SharedPreferences getDefaultSharedPreferences(Context context) { return context.getSharedPreferences(getDefaultSharedPreferencesName(context), getDefaultSharedPreferencesMode()); }
4.谨慎使用
SharedPreference将常驻内存,避免加载使用不到的,消耗内存
细分,将不常用与频繁使用的分开
ContextImpl中
private static ArrayMap<String, ArrayMap<String, SharedPreferencesImpl>> sSharedPrefs;
public SharedPreferences getSharedPreferences(String name, int mode) { SharedPreferencesImpl sp; synchronized (ContextImpl.class) { if (sSharedPrefs == null) { sSharedPrefs = new ArrayMap<String, ArrayMap<String, SharedPreferencesImpl>>(); } //根据包名进行一级分类 final String packageName = getPackageName(); ArrayMap<String, SharedPreferencesImpl> packagePrefs = sSharedPrefs.get(packageName); if (packagePrefs == null) { packagePrefs = new ArrayMap<String, SharedPreferencesImpl>(); sSharedPrefs.put(packageName, packagePrefs); } ........ //当前包名,二级分类(具体SharedPreferences) sp = packagePrefs.get(name); if (sp == null) { File prefsFile = getSharedPrefsFile(name); //我们获取的就是SharedPreferences的实现类SharedPreferencesImpl sp = new SharedPreferencesImpl(prefsFile, mode); packagePrefs.put(name, sp); return sp; } } ............ return sp; }
SharedPreferencesImpl中
private Map<String, Object> mMap;
SharedPreferencesImpl(File file, int mode) { .......... mLoaded = false; //是否加载解析过 mMap = null; //键值对就是放这里 startLoadFromDisk(); } private void startLoadFromDisk() { synchronized (this) { mLoaded = false; } new Thread("SharedPreferencesImpl-load") { public void run() { synchronized (SharedPreferencesImpl.this) { loadFromDiskLocked(); } } }.start(); } private void loadFromDiskLocked() { if (mLoaded) { return; } .......... Map map = null; StructStat stat = null; try { stat = Libcore.os.stat(mFile.getPath()); if (mFile.canRead()) { BufferedInputStream str = null; try { str = new BufferedInputStream( new FileInputStream(mFile), 16*1024); map = XmlUtils.readMapXml(str); //读取到的数据放内存中(以键值对形式) } catch (XmlPullParserException e) { Log.w(TAG, "getSharedPreferences", e); } catch (FileNotFoundException e) { Log.w(TAG, "getSharedPreferences", e); } catch (IOException e) { Log.w(TAG, "getSharedPreferences", e); } finally { IoUtils.closeQuietly(str); } } } catch (ErrnoException e) { } mLoaded = true;//执行完后更换状态,下次不再重复加载 if (map != null) { mMap = map; ........ } else { mMap = new HashMap<String, Object>(); } notifyAll(); }
获取值时
public int getInt(String key, int defValue) { synchronized (this) { awaitLoadedLocked(); Integer v = (Integer)mMap.get(key); return v != null ? v : defValue; } }
/** *如果SharedPreferences数据很多,那么首次解析,并紧跟着存取值时,主线程阻塞比较严重 */ private void awaitLoadedLocked() { ....... //上面创建SharedPreferencesImpl创建时,等loadFromDisk解析SharedPreference线程执行完后,才能跳过 while (!mLoaded) { try { wait();//这里是主线程,阻塞了 } catch (InterruptedException unused) { } } }