Android—数据持久化、SP源码
3种数据持久化:
- File:openFileInput(String fileName)、openFileOutput(String fileName, int mode)
不对存储的内容进行任何的格式化处理,比较合适存储一些简单的文本数据或二进制数据
- SharedPreferences
使用键值对的方式来存储数据,保存数据更加方便。数据以明文的方式保存在文件中,需要加密,一般保存应用设置。
- SQLite 继承SqLiteOpenHelper类创建数据库,
可以保存大量复杂的关系型数据
账号密码自动登陆:
在项目中,我们一般使用SharePrefences实现自动登录的功能,在登录成功后,将数据(用户名,密码)保存在SharePrefences中,然后再次进入app时,判断SharePrefences中有无数据,有的话就跳到主页面,没有的话就跳到登录页。
SharedPreferences 的源码实现:
SharedPreferences 是线程安全的。
final class SharedPreferencesImpl implements SharedPreferences {// 1、使用注释标记锁的顺序// Lock ordering rules:// - acquire SharedPreferencesImpl.mLock before EditorImpl.mLock// - acquire mWritingToDiskLock before EditorImpl.mLock// 2、通过注解标记持有的是哪把锁@GuardedBy("mLock")private Map<String, Object> mMap;@GuardedBy("mWritingToDiskLock")private long mDiskStateGeneration;public final class EditorImpl implements Editor {@GuardedBy("mEditorLock")private final Map<String, Object> mModified = new HashMap<>();}
}
SharedPreferences 是由 Context 返回的,获取 SharedPreferences 的方法定义在抽象类 Context 中。
public abstract SharedPreferences getSharedPreferences(String name, int mode);public abstract SharedPreferences getSharedPreferences(File file, int mode);
第一个方法是我们常用的,只要传入文件名,SP会自动寻找已有文件或创建,第二个是我们传入的文件。
所以 SharedPreferences 的操作,本质上就是对文件的操作,使用SharedPreferences时,只有第一次读取数据是有概率卡主线程几十到几百毫秒,而之后的读取时间几乎可以忽略不计。最后会落实到一个 xml 文件上。
@Overridepublic File getSharedPreferencesPath(String name) {return makeFilename(getPreferencesDir(), name + ".xml");}
标准路径在 /data/data/应用包名/shared_prefs 文件夹中,且都是 xml 文件。
commit 和 apply 的对比
EditorImpl 内部有一个内存缓存,用来保存用户修改后的操作:
private final Map<String, Object> mModified = Maps.newHashMap();
在执行 commit 或者 apply 前,比如editor.putString("Key","Value")会把修改存储在 mModified 中。
public Editor putString(String key, @Nullable String value) {synchronized (this) {mModified.put(key, value);return this;}}}
commit(同步):构造一个MemoryCommitResult来进行结果投递,在post任务以后会直接在当前线程进行wait。
apply(异步):构造一个MemoryCommitResult来调度IO(QueuedWork提供了singleThreadExecutor),apply()不会等待,而由QueuedWork的waitToFinish()方法的调用者(ActivityThread)来保证在某些时间点等待task的完成。
QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable);
QueuedWork:一个内部工具类,用于跟踪那些未完成的或尚未结束的全局任务。由 waitToFinish 方法保证执行,在 Activity onStop 以及 Service 处理 onStop,onStartCommand 时等待写入操作,所有排队的异步任务都在一个独立、专用的线程上处理。平时使用的时候,尽量使用 apply 避免卡住主线程。
apply方法造成的ANR:
在apply()方法中,首先会创建一个等待锁,最终更新文件的任务会交给QueuedWork.singleThreadExecutor()单个线程或者HandlerThread去执行,当文件更新完毕后会释放锁。 但当Activity.onStop()以及Service处理onStop等相关方法时,则会执行 QueuedWork.waitToFinish()等待所有的等待锁释放,因此如果SharedPreferences一直没有完成更新任务,有可能会导致卡在主线程,最终超时导致ANR。
加载 xml 数据文件
SharedPreferences 的加载流程,就是把文件的内容载入内存的过程。
private void loadFromDisk() {...str = new BufferedInputStream(new FileInputStream(mFile), 16*1024);map = XmlUtils.readMapXml(str);...}
本质上,就是读取一个 xml 文件,被内容解析为 Map 对象。这个 map 包含了我们之前保存的所有键值对的数据。
SharedPreferences 的读取非常快,载入完成后,后面的读操作都是针对 mMap 的,响应速度是内存级别的非常快。
SharedPreferences 不存放大量数据原因:
- apply操作耗时过久会导致ANR
- 如果数据量很大的话,返回的map对象会占很大一块内存
Android—数据持久化、SP源码相关推荐
- 实时获取股票数据的android app应用程序源码分享
From:http://www.jb51.net/article/72449.htm 本文我们分享一个实时获取股票数据的android app应用程序源码分享,可以作为学习使用,本文贴出部分重要代码, ...
- Android数据持久化
Android数据持久化(存储) 1.SharedPreferences SharedPreferences是Android提供的数据持久化的一种手段,适合单进程.小批量的数据存储与访问.Shared ...
- Android录音下————AudioRecord源码分析
Android录音下----AudioRecord源码分析 文章目录 Android录音下----AudioRecord源码分析 一.概述 1.主要分析点 2.储备知识 二.getMinBufferS ...
- Android 8.0系统源码分析--Camera processCaptureResult结果回传源码分析
相机,从上到下概览一下,真是太大了,上面的APP->Framework->CameraServer->CameraHAL,HAL进程中Pipeline.接各种算法的Node.再往下的 ...
- Android实用应用程序源码
andriod闹钟源代码 http://www.apkbus.com/android-20974-1-1.html android源码分享之指南针程序 http://www.apkbus.com/an ...
- 【Android RTMP】RTMPDumb 源码导入 Android Studio ( 交叉编译 | 配置 CMakeList.txt 构建脚本 )
文章目录 安卓直播推流专栏博客总结 一. RTMP 协议 二. RTMP 协议使用 三. RTMPDump 源码下载 四. RTMPDump 源码交叉编译 五. RTMPDump 源码导入 Andro ...
- Android Camera 系统架构源码分析
Android Camera 系统架构源码分析(1)---->Camera的初始化 Android Camera 系统架构源码分析(2)---->Camera的startPreview和s ...
- android 系统源码调试 局部变量值_如何方便快速的整编Android 9.0系统源码?
点击上方"刘望舒",选择"星标" 多点在看,就是真爱! 作者 : 刘望舒 | 来源 :刘望舒的博客地址:http://liuwangshu.cn/fram ...
- 140款Android开源优秀项目源码
140款Android开源优秀项目源码 BeautifulRefreshLayout-漂亮的美食下拉刷新 https://github.com/android-cjj/BeautifulRefresh ...
- android 三方_面试官送你一份Android热门三方库源码面试宝典及学习笔记
前言 众所周知,优秀源码的阅读与理解是最能提升自身功力的途径,如果想要成为一名优秀的Android工程师,那么Android中优秀三方库源码的分析和理解则是必备技能.就拿比较热门的图片加载框架Glid ...
最新文章
- 表 合并字段_多工作表动态合并,其实很简单
- 汇编语言——键盘输入字符
- java 去除干扰_【Selenium-WebDriver实战篇】Java丨验证码图片去除干扰像素,方便验证码的识别(转)...
- [python opencv 计算机视觉零基础到实战] 十二 直方图
- OCA读书笔记(8) - 管理用户安全
- 对刚iPad!华为最强Pad发布,独揽四项全球第一,3299元起!
- 我的世界服务器经常未响应是怎么回事,【电子世界】电脑经常出现“未响应”,该怎么办?...
- go 自定义error怎么判断是否相等_「GCTT 出品」Go 系列教程——30. 错误处理
- [Python] L1-030. 一帮一-PAT团体程序设计天梯赛GPLT
- inux中tail命令---用于查看文件内容
- ip头ttl_TCP/IP协议详解内容总结,看完恍然大悟
- android 情景模式来电铃声分析(一)
- 从零开始,做一个NodeJS博客(零):整体规(chui)划(niu)
- linux系统etc什么意思,etc.是什么意思 linux下的etc是什么意思
- 理解对比表示学习(Contrastive Learning)
- 8.19华为笔试题目c++
- Redis(9)——史上最强【集群】入门实践教程
- 北交大计算机在职非全考研初试心得
- 12个球,其中一个和其他的重量不一样,有一个天平,最多几次找出这个球
- Tivaware中MAP前缀函数与ROM前缀函数的区别
热门文章
- c mysql连接池_在LINUX下用C/C++写了一个连接池(访问MYSQL)的类
- LCD也可以模拟?这款模拟器别错过了!
- 一口气搞懂「链表」,就靠这20+张图了
- 硬件工程师如何成为焊接界的高手
- 拿不到offer全额退款 | 第四期人工智能 NLP / CV 课 培训招生
- httpd开启status模块_开启Apache Server Status
- 使用verilog实现基于FPGA的TDC设计
- verilog驱动ADC0809包括仿真测试
- Nexys4DDR+OV7670实现sobel算子边缘检测系统
- FPGA基础之LUT详解