Android之SharedPreferences
使用SharedPreference很久了,因为经常用到就准备总结下。
首先简单说下SharedPreference。
SharedPreferences是Android平台上一个轻量级的存储类,可以用来直接保存一些简单的数据,或者用来保存应用的一些常用配置,比如Activity状态,Activity暂停时,将此activity的状态保存到SharedPereferences中;当Activity重载,系统回调方法onSaveInstanceState时,再从SharedPreferences中将值取出。其中的原理是通过Android系统生成一个xml文件保到:/data/data/包名/shared_prefs目录下,类似键值对的方式来存储数据。
Sharedpreferences提供了常规的数据类型保存接口比如:int、long、boolean、String、Float、Set和Map这些数据类型。
直接上代码;
import java.util.Map;
import java.util.Set;
import android.content.Context;
import android.content.SharedPreferences;
public class SharedPreferencesUtils {
// 保存在手机里面的文件名
private static final String FILE_NAME = "shared_preferences";
//保存数据
public static void setParam(Context context, String key, Object object) {
String type = object.getClass().getSimpleName();
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
if (key != null) {
if (object instanceof Integer) {
editor.putInt(key, (Integer) object);
} else if (object instanceof Long) {
editor.putLong(key, (Long) object);
} else if (object instanceof Boolean) {
editor.putBoolean(key, (Boolean) object);
} else if (object instanceof Float) {
editor.putFloat(key, (Float) object);
} else if (object instanceof Set) {
editor.putStringSet(key, (Set<String>) object);
} else if (object instanceof String) {
editor.putString(key, String.valueOf(object));
}
editor.commit();
// SharedPreferencesCompat.apply(editor);
}
}
// 获取数据
public static Object getParam(Context context, String key, Object defaultObject) {
String type = defaultObject.getClass().getSimpleName();
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
if ("Integer".equals(type)) {
return sp.getInt(key, (Integer) defaultObject);
} else if ("Long".equals(type)) {
return sp.getLong(key, (Long) defaultObject);
} else if ("Boolean".equals(type)) {
return sp.getBoolean(key, (Boolean) defaultObject);
} else if ("Float".equals(type)) {
return sp.getFloat(key, (Float) defaultObject);
} else if ("Set".equals(type)) {
return sp.getStringSet(key, null);
} else if ("String".equals(type)) {
return sp.getString(key, null);
} else {
return null;
}
}
//移除指定key值对应的值
public static void removeKey(Context context, String key) {
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.remove(key);
editor.commit();
// SharedPreferencesCompat.apply(editor);
}
//清除所有数据
public static void clearAll(Context context) {
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.clear();
editor.commit();
// SharedPreferencesCompat.apply(editor);
}
//查询指定key是否已经存在
public static boolean containsKet(Context context, String key) {
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
return sp.contains(key);
}
//返回所有的键值对
public static Map<String, ?> getAll(Context context) {
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
return sp.getAll();
}
}
getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)方法中第二个参数详情如下
Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可以使用Context.MODE_APPEND
Context.MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用来控制其他应用是否有权限读写该文件。MODE_WORLD_READABLE:表示当前文件可以被其他应用读取;MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。
关于SharedPreference.Editor的commit()和apply()方法
可以看到我代码里面有注释掉SharedPreferencesCompat.apply(editor);代码。
代码详情如下:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.content.SharedPreferences;
/**
* 由于editor.commit方法是同步的,并且我们很多时候的commit操作都是UI线程中,毕竟是IO操作,所以尽可能采用异步操作;
* 所以我们使用apply进行替代,apply异步的进行写入
*/
public class SharedPreferencesCompat {
private static final Method sApplyMethod = findApplyMethod();
//反射查找apply的方法
@SuppressWarnings({ "unchecked", "rawtypes" })
private static Method findApplyMethod() {
try {
Class meditor = SharedPreferences.Editor.class;
return meditor.getMethod("apply");
} catch (NoSuchMethodException e) {
}
return null;
}
//如果找到则使用apply()执行,否则使用commit()
public static void apply(SharedPreferences.Editor editor) {
try {
if (sApplyMethod != null) {
sApplyMethod.invoke(editor);
return;
}
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
editor.commit();
}
}
SharedPreference.Editor的commit()方法,但是在studio提示使用apply()方法替换。
首先,两者都能实现shared存储的功能,但是两者还是有着一些不同
apply方法是将share的修改提交到内存而后异步写入磁盘,但是commit是直接写入磁盘,这就造成两者性能上的差异,犹如apply不直接写入磁盘而share本身是单例创建,apply方法会覆写之前内存中的值,异步写入磁盘的值只是最后的值,而commit每次都要写入磁盘,而磁盘的写入相对来说是很低效的,所以apply方法在频繁调用时要比commit效率高很多。
apply虽然高效但是commit也有着自己的优势那就是它可以返回每次操作的成功与否的返回值,根据它我们就可以在操作失败时做一些补救操作。综上,studio提示我们使用apply是在效率上的优化考虑,但是如果你很重视share是否成功操作,并希望在失败时做相应的提示或者补救commit还是更好的选择。