Activity之SharedPreferences探究(二)

2014-11-24 01:19:49 · 作者: · 浏览: 1
WriteRunnable != null) { postWriteRunnable.run(); } } }; final boolean isFromSyncCommit = (postWriteRunnable == null); // Typical #commit() path with fewer allocations, doing a write on // the current thread. if (isFromSyncCommit) { boolean wasEmpty = false; synchronized (SharedPreferencesImpl.this) { wasEmpty = mDiskWritesInFlight == 1; } if (wasEmpty) { writeToDiskRunnable.run(); return; } } QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable); }首先,这个函数ANDROID给了一段说明我们来看看: Enqueue an already-committed-to-memory result to be written to disk. 好像是说把数据写道DISK里面????

我们注意这个函数定义的一个Runnable的变量:writeToDiskRunnable它里面执行的重要代码是writeToFile(mcr);估计你看到这里就觉得有明白,他要干什么呢!的确就如你想的一样,其实是把刚刚存储在一个HashMap的数据写道一个文件里。 不信的话,我们继续看看writeToFile(mcr);这个函数干了些什么。

writeToFile(mcr);这个函数里面有这样一段重要的代码,你看了就彻底明白了,

            FileOutputStream str = createFileOutputStream(mFile);
            if (str == null) {
                mcr.setDiskWriteResult(false);
                return;
            }
            XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str);
            FileUtils.sync(str);
            str.close();
            ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
看看第一行代码 :FileOutputStream str = createFileOutputStream(mFile); 还记得一开始让你注意的那个文件吗?现在是不是终于用的了mFile。OK, 其实就是把数据写在了这个文件里面了。

XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str); mcr.mapToWriteToDisk这个数据是那里来的呢,其实 mapToWriteToDisk这个数据就是我们刚才说的那个存储数据的那个HashMap。看看如下的代码就知道了:

        private MemoryCommitResult commitToMemory() {
            MemoryCommitResult mcr = new MemoryCommitResult();
            synchronized (SharedPreferencesImpl.this) {
                // We optimistically don't make a deep copy until
                // a memory commit comes in when we're already
                // writing to disk.
                if (mDiskWritesInFlight > 0) {
                    // We can't modify our mMap as a currently
                    // in-flight write owns it.  Clone it before
                    // modifying it.
                    // noinspection unchecked
                    mMap = new HashMap
  
   (mMap);
                }
                mcr.mapToWriteToDisk = mMap;
  

在这个函数commitToMemory里紧接着就有如下代码
   for (Map.Entry
  
    e : mModified.entrySet()) {
                        String k = e.getKey();
                        Object v = e.getValue();
                        if (v == this) {  // magic value for a removal mutation
                            if (!mMap.containsKey(k)) {
                                continue;
                            }
                            mMap.remove(k);
                        } else {
                            boolean isSame = false;
                            if (mMap.containsKey(k)) {
                                Object existingValue = mMap.get(k);
                                if (existingValue != null && existingValue.equals(v)) {
                                    continue;
                                }
                            }
                            mMap.put(k, v);
                        }
  

看到了吗,这样一来原本暂时存储数据的mModified就把数据传出去了给了mapToWriteToDisk

这下明白了吧。实际上SharedPreferences的原理就是先把数据存储在hashmap,然后再写入一个文件里面。那么写入的这个文件是什么文件呢?文件名是什么呢?和一个APP有什么关系呢;还有上面说的“这说明一个特定的preferences,其实是共多个客户共享的”这里的多个客户共享是指什么呢?欲知详情,请看下面分解:

一般情况下,我们是通过如下的代码来获取一个SharedPreferences:

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);

(1)这里的this当然就是指当前Activity或是Service的Context,我们知道其实Activity和Service其实本质都是一样的,他们都是继承Context而来的。

(2)这里我们重点看这个函数getDefaultSharedPreferences(Context context)在PreferenceManager这个CLASS里面是这样定义的:

    public static SharedPreferences getDefaultSharedPreferences(Context context) {
        return context.getSharedPreferences(getDefaultSharedPreferencesName(context),
                getDefaultSharedPreferencesMode());
    }
看了这个函数,你一定豁然开朗了,getDefaultSharedPreferences是一个static 函数,实际上就是通过这个context来获取的SharedPreferences。首先我们来看看getDefaultSharedPreferencesName(context)这个函数传递的是什么参数:

    private static String getDefaultSharedPreferencesName(Context context) {
        return