Android之SharePreferences数据存储

SharedPreferences

SharedPreferences是一个轻量级的数据存储,并以key-value键值对的形式存在,符合xml文件存储

1.原型

public interface SharedPreferences

具体实现

//SharedPreferences其实是一个接口而已
public interface SharedPreferences {
    //定义一个用于在数据发生改变时调用的监听回调
    public interface OnSharedPreferenceChangeListener {
        //哪个key对应的值发生变化
        void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key);
    }

    //编辑SharedPreferences对象设定值的接口
    public interface Editor {
        //一些编辑存储基本数据key-value的接口方法
        Editor putString(String key, String value);
        Editor putStringSet(String key, Set<String> values);
        Editor putInt(String key, int value);
        Editor putLong(String key, long value);
        Editor putFloat(String key, float value);
        Editor putBoolean(String key, boolean value);
        //删除指定key的键值对
        Editor remove(String key);
        //清空所有键值对
        Editor clear();
        //同步的提交到硬件磁盘
        boolean commit();
        //将修改数据原子提交到内存,而后异步提交到硬件磁盘
        void apply();
    }

    //获取指定数据
    Map<String, ?> getAll();
    String getString(String key, String defValue);
    Set<String> getStringSet(String key, Set<String> defValues);
    int getInt(String key, int defValue);
    long getLong(String key, long defValue);
    float getFloat(String key, float defValue);
    boolean getBoolean(String key, boolean defValue);
    boolean contains(String key);

    //针对preferences创建一个新的Editor对象,通过它你可以修改preferences里的数据,并且原子化的将这些数据提交回SharedPreferences对象
    Editor edit();
    //注册一个回调函数,当一个preference发生变化时调用
    void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener);
    //注销一个之前(注册)的回调函数
    void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener);
}

2.方法

2.1 getPreferences(int mode)

public SharedPreferences getPreferences(int mode) {
        return getSharedPreferences(getLocalClassName(), mode);
    }

Activity的SharePreference实例获取方法只是对Context的getSharedPreferences再一次封装而已,使用getPreferences方法获取实例默认生成的xml文件名字是当前activity类名而已,此方法为Activity特有

2.2 getSharedPreferences (String name, int mode)

public abstract SharedPreferences getSharedPreferences (String name, int mode)
getSharedPreferences("config", Context.MODE_PRIVATE);

/data/data/com.example.reboottest/shared_prefs下生成了一个config.xml文件

获取SharedPreferences对象,其中第一参数为数据存储的文件名,并且会创建一个路径(data/packagename/shared_prefs/),第二个参数为Mode,具体有以下几种模式

  • MODE_APPEND

模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件

  • MODE_MULTI_PROCESS

多进程之间的使用

  • MODE_PRIVATE

默认的为0,即MODE_PRIVATE

  • MODE_WORLD_READABLE

表示当前文件可以被其他应用读取

  • MODE_WORLD_WRITEABLE

表示当前文件可以被其他应用写入

2.3 edit()

getSharedPreferences(context).edit()

在访问或修改数据之前需要先获取一个编辑器,通过 SharedPreferences.Editor方法

2.4 onSharedPreferenceChanged

public abstract void onSharedPreferenceChanged (SharedPreferences sharedPreferences, String key)

当数据被增加,删除,修改后会调用此接口

3.保存数据方式

  • commit()

在写操作commit时有三级锁操作,所以效率很低,所以当我们一次有多个修改写操作时等都批量put完了再一次提交确认,这样可以提高效率。

public boolean commit() {
    //1.先通过commitToMemory方法提交到内存
    MemoryCommitResult mcr = commitToMemory();
    //2.写文件操作
    SharedPreferencesImpl.this.enqueueDiskWrite(
            mcr, null /* sync write on this thread okay */);
    try {
        //阻塞等待写操作完成,UI操作需要注意!!!所以如果不关心返回值可以考虑用apply替代。
        mcr.writtenToDiskLatch.await();
    } catch (InterruptedException e) {
        return false;
    }
    //3.通知数据发生变化了
    notifyListeners(mcr);
    //4.返回写文件是否成功状态
    return mcr.writeToDiskResult;
}
  • apply()

其实和commit类似,只不过他是异步写的,没在当前线程执行写文件操作,还有就是他不像commit一样返回文件是否写成功状态

public void apply() {
    //有了上面commit分析,这个雷同,写数据到内存,返回数据结构
    final MemoryCommitResult mcr = commitToMemory();
    final Runnable awaitCommit = new Runnable() {
        public void run() {
            try {
                //等待写文件结束
                mcr.writtenToDiskLatch.await();
            } catch (InterruptedException ignored) {
            }
        }
    };

    QueuedWork.add(awaitCommit);
    //一个收尾的Runnable
    Runnable postWriteRunnable = new Runnable() {
        public void run() {
            awaitCommit.run();
            QueuedWork.remove(awaitCommit);
        }
    };
    //这个上面commit已经分析过的,这里postWriteRunnable不为null,所以会在一个新的线程池调用postWriteRunnable的run方法
    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);
}

  • commit与apply区别
return method
abstract void apply()
abstract boolean commit()

1.apply没有返回值,而commit有返回值boolean,表示是否提交成功
2.apply提交失败后没有任何提示
3.在SharedPreferences的Editor中如果用commit()方法提交数据,其过程是先把数据更新到内存,然后在当前线程中写文件操作,提交完成返回提交状态;如果用的是apply()方法提交数据,首先也是写到内存,接着在一个新线程中异步写文件,然后没有返回值

4.数据存储

4.1 写数据

通过edit()方法获取到haredPreferences.Editor编辑器

通过 putBoolean等方法添加数据,调用了Editor的putXXX后其实数据是没有存入SharePreference的,具体如下表

return method
abstract SharedPreferences.Editor clear()
abstract SharedPreferences.Editor putBoolean(String key, boolean value)
abstract SharedPreferences.Editor putFloat(String key, float value)
abstract SharedPreferences.Editor putInt(String key, int value)
abstract SharedPreferences.Editor putLong(String key, long value)
abstract SharedPreferences.Editor putString(String key, String value)
abstract SharedPreferences.Editor putStringSet(String key, Set values)
abstract SharedPreferences.Editor remove(String key)

最后commit保存修改,将Editor的数据存入SharePreference文件

       public Editor putBoolean(String key, boolean value) {
            //同步锁操作
            synchronized (this) {
                //将我们要存储的数据放入mModified集合中
                mModified.put(key, value);
                //返回当前对象实例,方便这种模式的代码写法:putXXX().putXXX();
                return this;
            }
        }

4.2 读数据

使用SharedPreferences对象来读取数据,一旦拿到SharePreference对象之后的getXXX操作其实都不再是文件读操作,如果读取到数据后,则获取,没有的话,读取默认的defValue默认值,具体代码如下:


return method
abstract boolean getBoolean(String key, boolean defValue)
abstract float getFloat(String key, float defValue)
abstract int getInt(String key, int defValue)
abstract long getLong(String key, long defValue)
abstract String getString(String key, String defValue)
abstract Set getStringSet(String key, Set defValues)
public boolean getBoolean(String key, boolean defValue) {
        //可以看见,和上面异步load数据使用的是同一个对象锁
        synchronized (this) {
            //阻塞等待异步加载线程加载完成notify
            awaitLoadedLocked();
            //加载完成后解析的xml数据放在mMap对象中,我们从mMap中找出指定key的数据
            Boolean v = (Boolean)mMap.get(key);
            //存在返回找到的值,不存在返回设置的defValue
            return v != null ? v : defValue;
        }
    }

6.实例演示

登录成功,保存对应的用户名及密码,登录不成功提示登录不成功,具体流程图如下:

Android之SharePreferences数据存储_第1张图片

MyPref.xml
at MyPref.xml                                                                 <
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="user">admin</string>
    <string name="pwd">123456</string>
</map>

7.项目代码

项目演练代码:https://github.com/409144245/SharedPerfTest

8.参考资料

参考链接

你可能感兴趣的:(Android)