目录
1)SP是什么、如何使用,SPUtils
2)SP的流程
3)comit和apply
一、SP是什么,如何使用,SPUtils
1.1 SP是什么?
SharedPreferences是Android平台提供的一种轻量级的数据存储方式,用于保存和读取应用程序的配置信息或其他简单的键值对数据。
使用SharedPreferences有以下几个优点:
- 简单易用:SharedPreferences提供了简单的API来保存和读取数据,无需编写复杂的数据库操作代码。
- 轻量级:相比于SQLite数据库等其他数据存储方式,SharedPreferences更加轻量级,适合存储少量的配置信息或用户偏好设置。
- 高效快速:由于数据存储在内部存储空间中,访问速度较快,适合存储需要频繁读取的数据。
- 跨进程共享:SharedPreferences可以被多个组件或进程共享访问,方便不同组件之间的数据交互和共享配置信息。
- 自动持久化:SharedPreferences会自动将数据持久化到磁盘上,即使应用关闭后再次启动也能保留之前的数据。
1.2 SP如何使用?
- 获取SharedPreferences实例:
val sharedPreferences = context.getSharedPreferences("my_preferences", Context.MODE_PRIVATE)
- 读取数据:
使用getString()方法读取String类型的值:val value = sharedPreferences.getString("key", "default_value")
使用getInt()方法读取Int类型的值:val value = sharedPreferences.getInt("key", default_value)
- 写入数据:
使用edit()方法获取SharedPreferences.Editor实例:val editor = sharedPreferences.edit()
使用putString()方法写入String类型的值:editor.putString("key", "value")
使用putInt()方法写入Int类型的值:editor.putInt("key", value)
- 提交或应用更改:
使用commit()方法提交更改:editor.commit()
使用apply()方法应用更改(异步操作):editor.apply()
1.3 SPUtils
public class SharedPreferencesUtils {
/**
* 保存在手机里面的文件名
*/
private static final String FILE_NAME = "share_date";
/**
* 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
* @param key
* @param object
*/
public static void setParam(String key, Object object){
String type = object.getClass().getSimpleName();
SharedPreferences sp = MyApplication.getContext().getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
if("String".equals(type)){
editor.putString(key, (String)object);
}
else if("Integer".equals(type)){
editor.putInt(key, (Integer)object);
}
else if("Boolean".equals(type)){
editor.putBoolean(key, (Boolean)object);
}
else if("Float".equals(type)){
editor.putFloat(key, (Float)object);
}
else if("Long".equals(type)){
editor.putLong(key, (Long)object);
}
editor.commit();
}
/**
* 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
* @param key
* @param defaultObject
* @return
*/
public static Object getParam(String key, Object defaultObject){
String type = defaultObject.getClass().getSimpleName();
SharedPreferences sp = MyApplication.getContext().getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
if("String".equals(type)){
return sp.getString(key, (String)defaultObject);
}
else if("Integer".equals(type)){
return sp.getInt(key, (Integer)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("Long".equals(type)){
return sp.getLong(key, (Long)defaultObject);
}
return null;
}
}
二、SP的流程
1)首先SP使用的是xml格式保存数据(如下图),文件位于应用的私有存储空间中【在/data/data/<package_name>/shared_prefs/目录下】。
2) SharedPreferences在读取xml文件时,会把整个xml文件加载到内存中,并以DOM的形式进行解析。
3)当新增一个K-V时,写入磁盘是全量更新,即会把之前的文件再次更新一遍。这意味着如果我们有100个数据,
如果只更新一项数据,也需要将所有数据转化成xml格式,然后再通过io写入文件中,这也就是导致使用SP可能存在ANR的情况出现。
三、comit和apply
SharedPreferences的commit()和apply()方法都用于提交对数据的修改
commit()方法:
commit()方法是同步地将修改集合中的数据写入磁盘。
它会阻塞当前线程直到写入操作完成,并返回一个boolean值表示是否成功。
如果写入过程中发生异常或失败,commit()方法会抛出异常并返回false。
对于SharedPreferences的commit()方法,由于它是同步的,会在主线程中执行写入操作。如果数据量较大或者磁盘IO速度较慢,可能会导致阻塞主线程,从而引发ANR错误。
apply()方法:
apply()方法是异步将修改集合中的数据写入磁盘。
它不会阻塞当前线程,而是立即返回。
写入在后台线程中进行,因此不会影响主线程的执行。
apply()方法没有返回值,也不会抛出异常,所以无法知道写入操作是否成功。
不过,apply也会导致ANR问题,具体可以看上面的源码, apply 其实利用了CountDownLatch机制,阻塞了当前线程,后续 Activity 的onStop()中会将这里的awaitCommit取出来执行,即UI线程会阻塞等待sp文件写入磁盘,为什么等待?为了保证异步任务及时完成。所以我们有的时候可以看到退出一个页面的时候,感觉也会卡,因为阻塞了主线程。
总结:SP,不能存储太多的信息,或者按分类去加载存储,很小很简单的数据可以保存到SP里面。