Activity之SharedPreferences探究(一)

2014-11-24 01:19:49 · 作者: · 浏览: 0

先说说SharedPreferences的定义:

在frameworks\base\core\java\android\content\SharedPreferences.java 这个文件里定义了SharedPreferences.的Interface有其二段原文需要说说:

第一段:

Interface for accessing and modifying preference data returned by {@linkContext#getSharedPreferences}. 这说明Preferences其实是实现了对数据的访问和修改的。

第二段

For any particular set of preferences, there is a single instance of this class that all clients share. 这说明一个特定的preferences,其实是共多个客户共享的。

通过上面两段英文说明,大致就知道SharedPreferences是什么了、是干什么的了。下面我一步一步来解开SharedPreferences秘密。

刚才说了SharedPreferences.java 只是定义了SharedPreferences的一个接口,其实真正实现它的是在这里:SharedPreferencesImpl.java。我们来看他到底在做什么:

首先看他的构造函数:

    SharedPreferencesImpl(File file, int mode) {
        mFile = file;
        mBackupFile = makeBackupFile(file);
        mMode = mode;
        mLoaded = false;
        mMap = null;
        startLoadFromDisk();
    }
这里我们关注这个函数的 第一个参数:file. 传递了一个文件。这个file是如何创建的,我们先不说,后面再议。 我们现在只关注SharedPreferencesImpl.的实现。

再看一个函数:

    public Editor edit() {
        // TODO: remove the need to call awaitLoadedLocked() when
        // requesting an editor.  will require some work on the
        // Editor, but then we should be able to do:
        //
        //      context.getSharedPreferences(..).edit().putString(..).apply()
        //
        // ... all without blocking.
        synchronized (this) {
            awaitLoadedLocked();
        }

        return new EditorImpl();
    }

当获取一个SharedPreferences实例时候,就需要调用这个函数才能获得这个SharedPreferences的操作。返回值是一个 Editor。那么对一个SharedPreferences的写数据、读数据等操作都是对这个SharedPreferences的Editor了,所以我们重点来看看Editor到底做了些什么。

先看看这个Editor的实现类EditorImpl其实是SharedPreferencesImpl的一个内部Final的类(下面给出一部分代码):

 public final class EditorImpl implements Editor {
        private final Map
  
    mModified = Maps.newHashMap();
        private boolean mClear = false;

        public Editor putString(String key, String value) {
            synchronized (this) {
                mModified.put(key, value);
                return this;
            }
        }
        public Editor putStringSet(String key, Set
   
     values) { synchronized (this) { mModified.put(key, (values == null)   null : new HashSet
    
     (values)); return this; } } public Editor putInt(String key, int value) { synchronized (this) { mModified.put(key, value); return this; } } ... ...
    
   
  
这里我们关注 他里面定义了一个HashMap的私有变量mModified。再看看putInt()z这些函数就知道, 对SharedPreferences写入数据,其实就是对mModified这个HashMap加入数据。你会说,不会吧,数据写入HashMap能够永久保存吗?当然不会。 不慌,我们来看看这个内部类的一个函数:

        public void apply() {
            final MemoryCommitResult mcr = commitToMemory();
            final Runnable awaitCommit = new Runnable() {
                    public void run() {
                        try {
                            mcr.writtenToDiskLatch.await();
                        } catch (InterruptedException ignored) {
                        }
                    }
                };

            QueuedWork.add(awaitCommit);

            Runnable postWriteRunnable = new Runnable() {
                    public void run() {
                        awaitCommit.run();
                        QueuedWork.remove(awaitCommit);
                    }
                };

            SharedPreferencesImpl.this.enqueueDiskWrite(mcr, postWriteRunnable);

            // Okay to notify the listeners before it's hit disk
            // because the listeners should always get the same
            // SharedPreferences instance back, which has the
            // changes reflected in memory.
            notifyListeners(mcr);
        }
重点看到里面有一行代码:SharedPreferencesImpl.this.enqueueDiskWrite(mcr, postWriteRunnable);那这个函数做了些什么呢?

    private void enqueueDiskWrite(final MemoryCommitResult mcr,
                                  final Runnable postWriteRunnable) {
        final Runnable writeToDiskRunnable = new Runnable() {
                public void run() {
                    synchronized (mWritingToDiskLock) {
                        writeToFile(mcr);
                    }
                    synchronized (SharedPreferencesImpl.this) {
                        mDiskWritesInFlight--;
                    }
                    if (post