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源码相关推荐

  1. 实时获取股票数据的android app应用程序源码分享

    From:http://www.jb51.net/article/72449.htm 本文我们分享一个实时获取股票数据的android app应用程序源码分享,可以作为学习使用,本文贴出部分重要代码, ...

  2. Android数据持久化

    Android数据持久化(存储) 1.SharedPreferences SharedPreferences是Android提供的数据持久化的一种手段,适合单进程.小批量的数据存储与访问.Shared ...

  3. Android录音下————AudioRecord源码分析

    Android录音下----AudioRecord源码分析 文章目录 Android录音下----AudioRecord源码分析 一.概述 1.主要分析点 2.储备知识 二.getMinBufferS ...

  4. Android 8.0系统源码分析--Camera processCaptureResult结果回传源码分析

    相机,从上到下概览一下,真是太大了,上面的APP->Framework->CameraServer->CameraHAL,HAL进程中Pipeline.接各种算法的Node.再往下的 ...

  5. Android实用应用程序源码

    andriod闹钟源代码 http://www.apkbus.com/android-20974-1-1.html android源码分享之指南针程序 http://www.apkbus.com/an ...

  6. 【Android RTMP】RTMPDumb 源码导入 Android Studio ( 交叉编译 | 配置 CMakeList.txt 构建脚本 )

    文章目录 安卓直播推流专栏博客总结 一. RTMP 协议 二. RTMP 协议使用 三. RTMPDump 源码下载 四. RTMPDump 源码交叉编译 五. RTMPDump 源码导入 Andro ...

  7. Android Camera 系统架构源码分析

    Android Camera 系统架构源码分析(1)---->Camera的初始化 Android Camera 系统架构源码分析(2)---->Camera的startPreview和s ...

  8. android 系统源码调试 局部变量值_如何方便快速的整编Android 9.0系统源码?

    点击上方"刘望舒",选择"星标" 多点在看,就是真爱! 作者 :  刘望舒  |  来源 :刘望舒的博客地址:http://liuwangshu.cn/fram ...

  9. 140款Android开源优秀项目源码

    140款Android开源优秀项目源码 BeautifulRefreshLayout-漂亮的美食下拉刷新 https://github.com/android-cjj/BeautifulRefresh ...

  10. android 三方_面试官送你一份Android热门三方库源码面试宝典及学习笔记

    前言 众所周知,优秀源码的阅读与理解是最能提升自身功力的途径,如果想要成为一名优秀的Android工程师,那么Android中优秀三方库源码的分析和理解则是必备技能.就拿比较热门的图片加载框架Glid ...

最新文章

  1. 表 合并字段_多工作表动态合并,其实很简单
  2. 汇编语言——键盘输入字符
  3. java 去除干扰_【Selenium-WebDriver实战篇】Java丨验证码图片去除干扰像素,方便验证码的识别(转)...
  4. [python opencv 计算机视觉零基础到实战] 十二 直方图
  5. OCA读书笔记(8) - 管理用户安全
  6. 对刚iPad!华为最强Pad发布,独揽四项全球第一,3299元起!
  7. 我的世界服务器经常未响应是怎么回事,【电子世界】电脑经常出现“未响应”,该怎么办?...
  8. go 自定义error怎么判断是否相等_「GCTT 出品」Go 系列教程——30. 错误处理
  9. [Python] L1-030. 一帮一-PAT团体程序设计天梯赛GPLT
  10. inux中tail命令---用于查看文件内容
  11. ip头ttl_TCP/IP协议详解内容总结,看完恍然大悟
  12. android 情景模式来电铃声分析(一)
  13. 从零开始,做一个NodeJS博客(零):整体规(chui)划(niu)
  14. linux系统etc什么意思,etc.是什么意思 linux下的etc是什么意思
  15. 理解对比表示学习(Contrastive Learning)
  16. 8.19华为笔试题目c++
  17. Redis(9)——史上最强【集群】入门实践教程
  18. 北交大计算机在职非全考研初试心得
  19. 12个球,其中一个和其他的重量不一样,有一个天平,最多几次找出这个球
  20. Tivaware中MAP前缀函数与ROM前缀函数的区别

热门文章

  1. c mysql连接池_在LINUX下用C/C++写了一个连接池(访问MYSQL)的类
  2. LCD也可以模拟?这款模拟器别错过了!
  3. 一口气搞懂「链表」,就靠这20+张图了
  4. 硬件工程师如何成为焊接界的高手
  5. 拿不到offer全额退款 | 第四期人工智能 NLP / CV 课 培训招生
  6. httpd开启status模块_开启Apache Server Status
  7. 使用verilog实现基于FPGA的TDC设计
  8. verilog驱动ADC0809包括仿真测试
  9. Nexys4DDR+OV7670实现sobel算子边缘检测系统
  10. FPGA基础之LUT详解