Android提供多种方式保存应用数据,其中一种方式是SharedPreferences,使用键值对保存私有基本的数据。所有的逻辑仅基于以下三个类:

SharedPreference

SharedPreference在这三个类是最重要的,负责获取(解析)存储数据。提供获取对象的编辑接口,在OnSharedPreferenceChangeListener中提供增加移出对象的接口。

  • 创建SharedPreference对象,需要上下文对象(可以是应用程序的上下文)。
  • getSharedPreferences 方法解析配置文件并创建相关的对象映射。
  • 通过上下文有多种创建它,强烈建议使用MODE_PRIVATE。因为创建一个可读写的文件是非常危险的,容易在应用中产生安全漏洞。
// parse Preference file
SharedPreferences preferences = context.getSharedPreferences("<span class="skimlinks-unlinked">com.example.app", Context.MODE_PRIVATE); // get values from Map
preferences.getBoolean("key", defaultValue)
preferences.get..("key", defaultValue) // you can get all Map but be careful you must not modify the collection returned by this
// method, or alter any of its contents.
Map<String, ?> all = preferences.getAll(); // get Editor object
SharedPreferences.Editor editor = preferences.edit(); //add on Change Listener
preferences.registerOnSharedPreferenceChangeListener(mListener); //remove on Change Listener
preferences.unregisterOnSharedPreferenceChangeListener(mListener); // listener example
SharedPreferences.OnSharedPreferenceChangeListener mOnSharedPreferenceChangeListener
=newSharedPreferences.OnSharedPreferenceChangeListener() {
@Override
publicvoidonSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
}
};

Editor

SharedPreferences.Editor是用来修改SharedPreferences对象值的接口。你在editor 做出的修改都是待处理的,并没有被复制到SharedPreferences里,直到你调用commit()或apply()修改才会被执行。

  • 使用简单的接口在Editor放入值。
  • 同步保存数据使用commit() 方法或者异步保存数据使用apply()方法会更快点。实际上不同的线程使用commit()会更快点,这是我喜欢使用commit()方法的原因。
  • 移出数据使用remove()方法,清除所有数据使用clear()方法。
// get Editor object
SharedPreferences.Editor editor = preferences.edit(); // put values in editor
editor.putBoolean("key", value);
editor.put..("key", value); // remove single value by key
editor.remove("key"); // remove all values
editor.clear(); // commit your putted values to the SharedPreferences object synchronously
// returns true if success
booleanresult = editor.commit(); // do the same as commit() but asynchronously (faster but not safely)
// returns nothing
editor.apply();

性能和注意事项

SharedPreferences是单例对象,你可以很容易获取你想要的引用。只在你第一次调用getSharedPreferences方法时打开文件时,创建一个实例对象。

// There are 1000 String values in preferences
SharedPreferences first = context.getSharedPreferences("com.example.app", Context.MODE_PRIVATE);
// call time = 4 milliseconds SharedPreferences second = context.getSharedPreferences("com.example.app", Context.MODE_PRIVATE);
// call time = 0 milliseconds SharedPreferences third = context.getSharedPreferences("com.example.app", Context.MODE_PRIVATE);
// call time = 0 milliseconds

SharedPreferences 是单例对象,你可以改变它的实例,不用担心同一个对象数据会不同。

first.edit().putInt(”key”,).commit();
intfirstValue = first.getInt(”key”,));
// firstValue is 15
intsecondValue = second.getInt(”key”,));
// secondValue is also 15

当你第一次调用get方法时,它解析对象并把放入map中,第二次获取数据从map 中获取,不需再解析。

first.getString(”key”,null)
// call time = 147 milliseconds first.getString(”key”,null)
// call time = 0 milliseconds second.getString(”key”,null)
// call time = 0 milliseconds third.getString(”key”,null)
// call time = 0 milliseconds

记住Preference的数据越大,get、commit、apply、remove和clear方法耗时越长。所以强烈建议把存储的数据分成小的对象。

当你的应用更新以后,你的Preferences不会被移除。所以有些情况下需要创建迁移数据的方案。比如,在应用启动的时候,你的应用解析本地JSON数据,实现这个你需要做的仅仅是存储标志数据(该数据是否为本地数据)。一段时间后,你更新JSON数据发布新的版本,用户会更新应用程序但是不会下载新的JSON数据,因为已经在本地存储了。

publicclassMigrationManager {
privatefinalstaticString KEY_PREFERENCES_VERSION ="key_preferences_version";
privatefinalstaticintPREFERENCES_VERSION =; publicstaticvoidmigrate(Context context) {
SharedPreferences preferences = context.getSharedPreferences("pref", Context.MODE_PRIVATE);
checkPreferences(preferences);
} privatestaticvoidcheckPreferences(SharedPreferences thePreferences) {
finaldoubleoldVersion = thePreferences.getInt(KEY_PREFERENCES_VERSION,); if(oldVersion < PREFERENCES_VERSION) {
finalSharedPreferences.Editor edit = <spanclass="skimlinks-unlinked">thePreferences.edit</span>();
<spanclass="skimlinks-unlinked">edit.clear</span>();
edit.putInt(KEY_PREFERENCES_VERSION, currentVersion);
edit.commit();
}
}
}

SharedPreferences 数据存储在app文件夹下的xml文件下。

// yours preferences
/data/data/YOUR_PACKAGE_NAME/shared_prefs/YOUR_PREFS_NAME.xml // default preferences
/data/data/YOUR_PACKAGE_NAME/shared_prefs/YOUR_PACKAGE_NAME_preferences.xml

示例代码

publicclassPreferencesManager {

    privatestaticfinalString PREF_NAME ="<span class="skimlinks-unlinked">com.example.app.PREF_NAME";
privatestaticfinalString KEY_VALUE ="<span class="skimlinks-unlinked">com.example.app.KEY_VALUE"; privatestaticPreferencesManager sInstance;
privatefinalSharedPreferences mPref; privatePreferencesManager(Context context) {
mPref = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
} publicstaticsynchronizedvoidinitializeInstance(Context context) {
if(sInstance ==null) {
sInstance =newPreferencesManager(context);
}
} publicstaticsynchronizedPreferencesManager getInstance() {
if(sInstance ==null) {
thrownewIllegalStateException(PreferencesManager.class.getSimpleName() +
" is not initialized, call initializeInstance(..) method first.");
}
returnsInstance;
} publicvoidsetValue(longvalue) {
mPref.edit()
.putLong(KEY_VALUE, value)
.commit();
} publiclonggetValue() {
returnmPref.getLong(KEY_VALUE,);
} publicvoidremove(String key) {
mPref.edit()
.remove(key)
.commit();
} publicbooleanclear() {
returnmPref.edit()
.clear()
.commit();
}
}

本文代码可以在github上找到。

Android SharedPreference最佳实践的更多相关文章

  1. Android开发最佳实践《IT蓝豹》

    Android开发最佳实践   移动开发Android经验分享应用GoogleMaterial Design 摘要:前 段时间,Google公布了Android开发最佳实践的一系列课程,涉及到一些平时 ...

  2. Android开发最佳实践

    Android开发最佳实践 摘要 ●使用 Gradle 和它推荐的工程结构 ●把密码和敏感数据放在gradle.properties ●不要自己写 HTTP 客户端,使用Volley或OkHttp库 ...

  3. [转]Android开发最佳实践

    ——欢迎转载,请注明出处 http://blog.csdn.net/asce1885 ,未经本人同意请勿用于商业用途,谢谢—— 原文链接:https://github.com/futurice/and ...

  4. Android 异常处理最佳实践

    一个好的app 异常处理机制 我认为应该至少包含以下几个功能: 1.能把错误信息上传到服务器  让开发者可以持续改进app 2.错误信息至少应该包含 是否在主进程 是否在主线程 等可以帮助程序员定位的 ...

  5. 转:使用Android API最佳实践

    原文来自于:http://blog.jobbole.com/65170/ 写在前面 现在,Android应用程序中集成第三方API已十分流行.应用程序都有自己的网络操作和缓存处理机制,但是大部分比较脆 ...

  6. Android 涂鸦最佳实践

    Android中实现手势画图一般都两种方式,一是直接在View上绘制,而是使用SurfaceView. 两者还是有一些差别的.简介下. View:显示视图,内置画布,提供图形绘制函数.触屏事件.按键事 ...

  7. Android 开发最佳实践

    原文地址:https://github.com/futurice/android-best-practices/blob/master/translations/Chinese/README.cn.m ...

  8. (转)iOS 最佳实践

    本文转自http://www.jianshu.com/p/b0bf2368fb95 感谢作者和译者 iOS最佳实践 iOS最佳实践 译者注 本文翻译自 futurice 公司的 iOS Good Pr ...

  9. Android和PHP开发最佳实践

    Android和PHP开发最佳实践 <Android和PHP开发最佳实践>基本信息作者: 黄隽实丛书名: 移动应用开发技术丛书出版社:机械工业出版社ISBN:9787111410508上架 ...

随机推荐

  1. 获取checkbox 的选中状态的id、checkbox的一些操作

    var id_array=new Array(); $('input[name="id"]:checked').each(function(){ id_array.push($(t ...

  2. objective -c 知識点

    那么类别与继承相比,有什么缺点吗?类别不可以声明新的成员变量,而且一旦你定义的方法与原始类中的方法名称相同,那么原始方法将被隐藏起来,因为不是继承结构,你不能在类别中的方法使用super 激活原始类的 ...

  3. Flink资料(6) -- 如何添加一个新的Operator

    false false false false EN-US ZH-CN X-NONE /* Style Definitions */ table.MsoNormalTable {mso-style-n ...

  4. spring4之依赖注入的三种方式

    1.Setter注入 <bean id="helloWorld" class="com.jdw.spring.beans.HelloWorld"> ...

  5. java设计模式之 单例模式 Singleton

    static 的应用 单例模式 Singleton 单例:保证一个类在系统中最多只创建一个实例. 好处:由于过多创建对象实例,会产生过多的系统垃圾,需要GC频繁回收,由于GC会占用较大的系统资源,所有 ...

  6. linux----定义命令别名

    1.定义命令别名的语法: alias nickName='command'#用于定义. unalias  nickName#用于撤消一个别名的定义. 如:alias cls='clear' 2.应该要 ...

  7. 基于ArcEngine的影像数据管理系统研制

    基于ArcEngine的影像数据管理系统研制 如果批处理,速度很慢,效率低. 详情如下: 分成很多小块的影像数据,要达到连续显示的效果,并导入ArcSDE for SQL Server中以方便管理.在 ...

  8. Ubuntu eclipse :An error has occurred. See the log file

    安装eclipse: sudo apt-get install eclipse-platform 调整java: sudo update-alternatives --config java 启动: ...

  9. Xcode 3.2.5免证书开发调试

    Xcode 3.2.5免证书开发调试 xcode3.2.5 应该没人用了.这里做个保存而已. Xcode编译遇到过 Code Sign error: a valid provisioning prof ...

  10. 深入分析MFC文档视图结构(项目实践)

    k_eckel:http://www.mscenter.edu.cn/blog/k_eckel 文档视图结构(Document/View Architecture)是MFC的精髓,也是Observer ...