关于 SharedPreferences 的一些思考

对于 SharedPreferences ,想必不会陌生,通常我们会这么用

Editor sharedata = getSharedPreferences("data", 0).edit();
sharedata.putString("item","hello getSharedPreferences");
sharedata.commit();

SharedPreferences 的百度定义如下:

SharedPreferences是Android平台上一个轻量级的存储类,用来保存应用的一些常用配置,比如Activity状态,Activity暂停时,将此activity的状态保存到SharedPereferences中;当Activity重载,系统回调方法onSaveInstanceState时,再从SharedPreferences中将值取出。
SharedPreferences提供了java常规的Long、Int、String等类型数据的保存接口。 [1] SharedPreferences类似过去Windows系统上的ini配置文件,但是它分为多种权限,可以全局共享访问。
提示最终是以xml方式来保存,整体效率来看不是特别的高,对于常规的轻量级而言比SQLite要好不少,如果真的存储量不大可以考虑自己定义文件格式。xml处理时Dalvik会通过自带底层的本地XML Parser解析,比如XMLpull方式,这样对于内存资源占用比较好。

原理:

内部是以 XML 结构保存在 /data/data/包名/shared_prefs 文件夹下,数据以键值对的形式保存。

文件内容:



    

提交方式:

apply:异步执行,没有返回值;
commit:同步执行,有返回值。

创建模式:

MODE_PRIVATE:默认模式,该模式下创建的文件只能被当前应用或者与该应用具有相同SharedUserID的应用访问。
MODE_WORLD_READABLE:允许其他应用读取这个模式创建的文件。在Android N上使用该模式将抛出SecurityException异常。
MODE_WORLD_WRITEABLE:允许其他应用写入这个模式创建的文件。在Android N上使用该模式将抛出SecurityException异常。
MODE_APPEND:如果文件已经存在了,则在文件的尾部添加数据。
MODE_MULTI_PROCESS:SharedPreferences加载标志,当设置了该标志,则在磁盘上的文件将会被检查是否修改了,尽管SharedPreferences实例已经在该进程中被加载了。(鸡肋,不要用,推荐用ContentProvider)

到此,基本的使用上已经没什么问题了,对于部分配置参数的存取上,都可以通过这些来实现。

SharedPreferences 真的就这些内容吗?

并不是,它还有
registerOnSharedPreferenceChangeListener、unregisterOnSharedPreferenceChangeListener 设置监听
getAll 获取所有的键值对

更有提供的preference以键值对的方式来处理这种情况:自动保存设置的数据,并立时生效。实现即为使用 SharedPreferences 。

常见的Preference控件有:

直接子类:DialogPreference, PreferenceGroup, RingtonePreference, TwoStatePreference
非直接子类:CheckBoxPreference, EditTextPreference, ListPreference, MultiSelectListPreference, PreferenceCategory, PreferenceScreen, SwitchPreference

注意,在API 29 开始被弃用,使用上需注意。

在看ACRA项目时有看到使用registerOnSharedPreferenceChangeListener来设置监听,以此实现开关功能,这用法真是巧妙,因为这个解决了耦合的问题,通常情况下,我们设置一个开关如下:

public class A{
	private boolean isEnable = false;
	...
	public void setEnable(boolean enable){
		this.isEnable = enable;
	}
	...
}

这种方式显而易见,容易。
使用时,只需要拿到实例操作即可

A a = new A();
a.setEnable(true);

在学习开源项目ACRA时,看到如下用法

final SharedPreferences prefs = new SharedPreferencesFactory(app, config).create();
...
ErrorReporterImpl reporter = new ErrorReporterImpl(app, config, enableAcra, supportedAndroidVersion, checkReportsOnApplicationStart);
prefs.registerOnSharedPreferenceChangeListener(reporter);
...

其中,reporter对象为一个错误捕获实现,实现了SharedPreferences.OnSharedPreferenceChangeListener,其代码如下,

@Override
public void onSharedPreferenceChanged(@NonNull SharedPreferences sharedPreferences, @Nullable String key) {
    if (ACRA.PREF_DISABLE_ACRA.equals(key) || ACRA.PREF_ENABLE_ACRA.equals(key)) {
        setEnabled(SharedPreferencesFactory.shouldEnableACRA(sharedPreferences));
    }
}

是不是忽然有个大胆的想法

如果在项目中,我的一些控制器在上层想设置某个启用与否,可以通过此方式进行解耦控制,大大降低了模块与模块的联系,从而在一些功能的升级、模块的修改上更加方便,无需考虑关联性修改的问题。

希望SharedPreferences的这种用法对你有用

你可能感兴趣的:(分享,思考感悟)