目录:
- 简介
- SharedPreferences使用步骤
- 生成SharedPreferences的三种方式
- 使用SharedPreferences注意事项
- SharedPreferences注册监听
- SharedPreferences的简单封装
简介:
SharedPreferences,是Android上一种轻量级数据储存方式。主要用于储存App配置信息;支持储存数据类型:boolean、int、float、long、String。
SharedPreferences使用步骤:
生成SharedPreferences对象;
生成editor对象;
由editor对SharedPreferences进行put、delete以及clear操作;
commit()/apply()提交;
生成SharedPreferences的三种方式:
PreferenceManager.getDefaultSharedPreferences(Context)生成:包名_preferences.xml;
Activity.getPreferences(int mode)生成:Activity名.xml;
Context.getSharedPreferences(String name,int mode)生成:name.xml
注:
- 生成的文件位置位于:data/data/包名/shared_prefs/目录下;
- mode一般为:MODE_PRIVATE;
使用SharedPreferences注意事项:
1. SharedPreferences文件应尽量小
SharedPreferences在创建的时候,会将整个文件加载到内存。如果文件过大,将会导致下列问题:
- 第一次从SharedPreferences中取值时,有可能阻碍主线程,使界面卡顿、掉帧;
- 解析SharedPreferences时会产生大量的临时对象,导致频繁GC,使界面卡顿;
- SharedPreferences中的key和value会一直存在内存中,占据大量内存;
2. 尽量少edit和apply提交
- 每次edit都会创建一个Editor对象,额外占据内存;
- 多次apply会造成界面的卡顿;
3. 不推荐使用SharedPreferences进行跨进
综上三点可以查看Android请不要滥用SharedPreference从源码上理解缘由。
SharedPreferences注册监听:
OnSharedPreferenceChangeListener是Android中SharedPreference文件发生变化的监听器。
当如下使用时:
@Override
protected void onCreate(Bundle savedInstanceState) {
PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener(){
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Log.i("SP-->" ,"onSharedPreferenceChanged");
}
});
}
总是会出现回调方法无法回调的问题,其原因为:注册的监听器使用了匿名内部类。由于listener保持在WeakHashMap中,这就意味着不能监听一个匿名内部类,因为listener会成为垃圾收集的目标,只要离开目前的作用范围,它将会被作为垃圾收集,从WeakHashMap中删除并停止工作。源码实现:
final class SharedPreferencesImpl implements SharedPreferences {
......
......
......
@GuardedBy("mLock")
private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
......
......
......
public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
synchronized(mLock) {
mListeners.put(listener, CONTENT);
}
}
}
解决方案:
网上有很好的解决方案,可自行查阅,在这里不再贴代码,简单说一下解决思路:
- 将监听器listener作为成员变量;
- 在onResume()中注册监听;
- 在onPause()中注销监听;
也有在onStart()和onStop()中注册与注销的,不过笔者个人认为在onResume()和onPause()中进行注册和注销更有利于内存的使用,还望大家斟酌使用。
SharedPreferences的简单封装:
public class SharedPreferenceUtils {
private static SharedPreferences sharedPreferences;
private static SharedPreferences.Editor editor;
/**
* 使用PreferenceManager生成SharedPreferences
* @param context getApplicationContext();
* @return sharedpreferences
*/
private SharedPreferences getSharedPreferences(Context context){
return PreferenceManager.getDefaultSharedPreferences(context);
}
/**
* 使用Activity生成SharedPreferences
* @param activity 相关联的Activity
* @param mode 文件模式
* @return SharedPreferences
*/
private SharedPreferences getSharedPreferences(Activity activity,int mode){
return activity.getPreferences(mode);
}
/**
* 使用Context生成SharedPreferences
* @param context 上下文
* @param name 文件名
* @param mode 文件模式
* @return SharedPreferences
*/
private SharedPreferences getSharedPreferences(Context context,String name,int mode){
return context.getSharedPreferences(name,mode);
}
private void put(HashMap<String,Object> data){
editor = sharedPreferences.edit();
Set<String> keys = data.keySet();
for (String key : keys){
Object value = data.get(key);
parseValue(editor,key,value);
}
editor.apply();
}
private void put(String key, Object value) {
editor = sharedPreferences.edit();
parseValue(editor,key,value);
editor.apply();
}
private Object getData(String key, Class<? extends Object> valueClass){
if (valueClass.equals(Integer.class)){
return sharedPreferences.getInt(key,0);
}else if (valueClass.equals(String.class)){
return sharedPreferences.getString(key,"null");
}else if (valueClass.equals(Float.class)){
return sharedPreferences.getFloat(key,0f);
}else if (valueClass.equals(Boolean.class)){
return sharedPreferences.getBoolean(key,false);
}else if (valueClass.equals(Long.class)){
return sharedPreferences.getLong(key,0L);
}
return null;
}
private void clear(){
sharedPreferences.edit().clear().apply();
}
private void deleteData(String key){
sharedPreferences.edit().remove(key).apply();
}
private void deleteData(String[] keys){
editor = sharedPreferences.edit();
for (String key : keys){
editor.remove(key);
}
editor.apply();
}
private void parseValue(SharedPreferences.Editor editor,String key,Object value){
Class<? extends Object> valueClass;
valueClass = value.getClass();
if (valueClass.equals(Integer.class)){
editor.putInt(key,(int)value);
}else if (valueClass.equals(String.class)){
editor.putString(key,(String)value);
}else if (valueClass.equals(Float.class)){
editor.putFloat(key,(float)value);
}else if (valueClass.equals(Boolean.class)){
editor.putBoolean(key,(boolean)value);
}else if (valueClass.equals(Long.class)){
editor.putLong(key,(long)value);
}
}
public static class Builder{
private WeakReference<SharedPreferenceUtils> weakSPUtils;
private SharedPreferenceUtils spUtils;
public Builder(Context context){
isSPUtilsEnpty();
sharedPreferences = spUtils.getSharedPreferences(context);
}
public Builder(Activity activity,int mode){
isSPUtilsEnpty();
sharedPreferences = spUtils.getSharedPreferences(activity,mode);
}
public Builder(Context context,String name,int mode){
isSPUtilsEnpty();
sharedPreferences = spUtils.getSharedPreferences(context,name,mode);
}
public Builder putData(HashMap<String,Object> data){
spUtils.put(data);
return this;
}
public Builder putData(String key,Object value){
spUtils.put(key,value);
return this;
}
public Builder deleteData(String[] keys){
spUtils.deleteData(keys);
return this;
}
public Builder deleteData(String key){
spUtils.deleteData(key);
return this;
}
public Builder clear(){
spUtils.clear();
return this;
}
public Object getData(String key,Class<? extends Object> valueClass){
return spUtils.getData(key,valueClass);
}
public Builder create(){
return this;
}
private void isSPUtilsEnpty() {
if (weakSPUtils.get() == null){
weakSPUtils = new WeakReference<SharedPreferenceUtils>(new SharedPreferenceUtils());
spUtils = weakSPUtils.get();
}
}
}
}
封装支持的功能:
- 单个和批量添加:putData(HashMap data)、putData(key,value);
- 单个和批量删除:deleteData(keys)、deleteData(key);
- 获取数据:getData(key,valueClass);
- 清理数据:clear();
简单使用:
案例:批量添加数据
HashMap<String,Object> data = new HashMap<>();
data.put("int",1);
data.put("float",2.123f);
data.put("String","abc");
SharedPreferenceUtils.Builder builder = new SharedPreferenceUtils.Builder(getApplicationContext())
.putData(data)
.create();