Android之SharedPreferences

版权声明:本文为博主原创文章,未经博主允许不的转载。谢谢! https://blog.csdn.net/niu9799/article/details/81033238

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还是更好的选择。

猜你喜欢

转载自blog.csdn.net/niu9799/article/details/81033238