阅读 103

sharing和shared,preferences窗口

前言: SharedPreferences是开发中的常见类,主要作用是可持续存储本地轻量级数据,便于简单的数据存储和逻辑判断。 由于具有简单和非结构化的特点,在一般简单的商务场景中比数据库更实用。 本文主要说明使用中性能优化的相关注意事项。

1、避免存储大量数据SharedPreferences最初旨在提供轻量级数据存储方案。 因此,无法与数据库进行比较。 如果存储在SharedPreferences中的数据过多(get* ) ),则调用时会长时间加载,这会影响主线程,从而尽可能保证SharedPreferences

每次调用apply (或commit )时都会创建一个空文件,并一次写入所有数据,而不是增量写入。 让我们看看源代码。 SharedPreferences是一个接口,具体实现由SharedPreferencesImpl实现类进行。)

@Overridepublic boolean commit () { long startTime=0; if(debug ) start time=system.current time millis ); } memorycommitresultmcr=committomemory (; sharedpreferencesimpl.this.enqueuediskwrite (MCR,null/* syncwriteonthisthreadokay */); try { MCR.writtentodisklatch.await (; } catch (内部扩展) { return false; (finally(if ) debug ) log.d (tag,mFile.getName ) ) : ) MCR.memorystategeneration (committed after ) ) sy stated return mcr.writeToDiskResult; }因此,数据越大,时间越长,可能会引起ANR。

由于大多数APP应用程序在Application中使用SharedPreferences进行逻辑确定,因此建议在启动时根据需要保留Application和MainActivity使用的SharedPreferences 使用较小的SharedPreferences可以加快值的检索过程,还可以减少App首次启动时的内存消耗,从而提高启动速度和性能。

2、尽快初始化SharedPreferences,并在没有缓存时进行初始化,很费时间。 一般来说,写代码如下。

sp=context.getsharedpreferences (sp _ dwf _ user ),Context.MODE_PRIVATE; editor=sp.edit (; editor.putString(key,(string ) obj ).commit ); 这种初始化后立即处理对象的方式是通常的写法,但效率低下。 尽可能地edit ) )之前,为了完成SharedPreferences的加载,当前页面所需的SharedPreferences对象为activity oncreate ) )或fragment oncreate

3、为了避免key太长,我们先看看SharedPreferences使用的数据结构。

1.ContextImpl中的sSharedPrefsCache是阵列地图。

classcontextimplextendscontext { ./* * mapfrompackagename,to preference name, tocachedpreferences.*/@ guarded by (context impl.class ) ) private static ArrayMapString,ArrayMapFile,shared preferences

@ overridepublicsharedpreferencesgetsharedpreferences (文件文件文件,int

mode) { SharedPreferencesImpl sp; synchronized (ContextImpl.class) { final ArrayMap<File, SharedPreferencesImpl> cache = getSharedPreferencesCacheLocked(); sp = cache.get(file); ... }}

3.SharedPreferencesImpl内部的mMap是HashMap:

if (thrown == null) { if (map != null) { mMap = map; mStatTimestamp = stat.st_mtim; mStatSize = stat.st_size; } else { mMap = new HashMap<>(); }}

为什么一会儿用ArrayMap,一会儿用HashMap呢?

从Android角度来说,当数据有下列特征时可以选择ArrayMap:
(1)数据量小(<1000)时,因为二分查找,所以速度更快。
(2)数据量小,无需考虑扩容的情况。
(3)运行期间不执行或较少执行remove操作。
(4)数据的插入操作十分低频。
(5)本身包含子map对象,即map中存map的结构。

一般App开发中用到的SharedPreferences个数很有限,一般人不会用超过20个,所以源码中用到了ArrayMap。而SharedPreferences内部存值用到了HashMap,因为HashMap的插入和查找效率都很高,并且系统也不知道开发者会存多少数据到SharedPreferences中,所以用HashMap能更好的扩容。

HashMap的数据结构本身就是比较耗内存的,甚至在没有数据的时候,初始化的时候已经分配了空间,所以会有基础的内存开销,而ArrayMap=0。

最后,如果SharedPreferences中存放的key过长,那么计算hashcode的时间就会加长,这肯定会影响效率,所以一般key不要太长,除非是为了某些情况取名冲突。

4、多次操作,批量提交

每次代码提交都是有性能代价的,官方推荐多次修改完成后,进行一次性提交。

一般情况下,SharedPreferences的效率并不会成为App性能的障碍,举个典型的例子,用户退出App时会保存用户的当前状态,我们可以将这种大量的相关性数据变成一个javabean对象,方便一次性存取。

5、缓存Editor对象

在SharedPreferencesImpl中,Editor对象的源码如下:

@Overridepublic Editor edit() { // TODO: remove the need to call awaitLoadedLocked() when // requesting an editor. will require some work on the // Editor, but then we should be able to do: // // context.getSharedPreferences(..).edit().putString(..).apply() // // ... all without blocking. synchronized (mLock) { awaitLoadedLocked(); } return new EditorImpl();}

也就是说每次调用edit()方法都会new出一个editor对象,这没有必要,如果我们当前类中有多处使用editor的地方,可以将editor变成类的成员变量,这样会减少内存波动。

6、不存放HTML和JSON

对于HTML和JSON数据,很多开发者都是直接toString()或者Json.toJsonString()后就放到SharedPreferences中,当然,SharedPreferences是可以存放string类型的数据,但是这样的数据存放在XML中会出现很多转义符号,在解析取出值的时候,如果系统碰到特殊符号就会进行特殊的处理,从而引发额外的字符串拼接以及函数调用。这类文件往往都很大,取值时SharedPreferences会将它直接缓存到内存中,进行静态持有直到App退出时才会被释放。

SharedPreferences虽然好用,但是需要思考这些对象是否可以直接存放在磁盘中,她们是否真的需要key-value关系。

7、拆分高频和低频操作

尽量避免写完之后立刻读值的操作,这种高频读写的操作放在一起就会出现因为锁而引起的开销。对于高频写操作的值与高频读操作的值,可以适当的拆分到不同的SharedPreferences中,可以减少一个文件中同步锁的竞争。当然这种情况也不常见,如果项目没有遇到性能瓶颈,可以忽略。


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐