昨晚公司进行团建 ,突突了两瓶汾酒结果都嗨了 ,亲眼见证程序员其实也是多才多艺的 ,有几个小伙伴简直就是被代码耽误的歌手 。

PS :今天在家使用室友的 MacBookPro(TouchBar)的电脑进行工作 ,讲真的的确实比我的 MacBookPro 舒服 。

Android的性能优化几乎是面试必考题 ,答案的结构很唯一无非就是内存优化 、卡顿优化 、I/O优化 、UI优化 、启动优化 、储存优化 、闪退优化 、网络优化 、耗电优化 、包体积优化等等 。但是面试的时候只要把任意一个结构突突的很透彻 ,当前的Offer已经成了一半了 ;如果可以把常用的内存优化 、卡顿优化  、I/O 优化 、启动优化突突的很透彻 ,Offer已经成了 ;要是在加上一些储存 、闪退 、网络 、包体积的话 ,就可以主动地谈薪资(有一个情况可能不太行 ,就是公司的需求是写代码的 ,对技术要求无的)。

PS:会一直更新这个系列 。

「 内存优化 」、「 卡顿优化 」、「 I/O优化 」

「 UI 优化 」、  「 启动优化 」、「 储存优化 」

「 闪退优化 」、「 网络优化 」、「 耗电优化 」
「 包体积优化 」。

Android 的存储基础

1. Android 分区

对于 Android 来说,我们首先应该对 Android 分区的架构和作用有所了解。在我们熟悉的 Windows 世界中,我们一般都把系统安装在 C 盘,然后还会有几个用来存放应用程序和数据的分区。

什么是分区呢?

分区简单来说就是将设备中的存储划分为一些互不重叠的部分,每个部分都可以单独格式化,用作不同的目的。这样系统就可以灵活的针对单独分区做不同的操作,例如在系统还原(recovery)过程,我们不希望会影响到用户存储的数据。

从上面的表中你可以看到,每个分区非常独立,不同的分区可以使用的不同的文件系统。其中比较重要的有:

  • /system 分区:它是存放所有 Google 提供的 Android 组件的地方。这个分区只能以只读方式 mount。这样主要基于稳定性和安全性考虑,即使发生用户突然断电的情况,也依然需要保证 /system 分区的内容不会受到破坏和篡改。
  • /data 分区:它是所有用户数据存放的地方。主要为了实现数据隔离,即系统升级和恢复的时候会擦除整个 /system 分区,但是却不会影响 /data 的用户数据。而恢复出厂设置,只会擦除 /data 的数据。
  • /vendor 分区:它是存放厂商特殊系统修改的地方。特别是在 Android 8.0 以后,隆重推出了“Treble”项目。厂商 OTA 时可以只更新自己的 /vendor 分区即可,让厂商能够以更低的成本,更轻松、更快速地将设备更新到新版 Android 系统。

2. Android 存储安全

除了数据的分区隔离,存储安全也是 Android 系统非常重要的一部分,存储安全首先考虑的是权限控制。

第一,权限控制

Android 的每个应用都在自己的 应用沙盒 内运行,在 Android 4.3 之前的版本中,这些沙盒使用了标准 Linux 的保护机制,通过为每个应用创建独一无二的 Linux UID 来定义。简单来说,我们需要保证微信不能访问淘宝的数据,并且在没有权限的情况下也不能访问系统的一些保护文件。

第二,数据加密

除了权限的控制,用户还会担心在手机丢失或者被盗导致个人隐私数据泄露。加密或许是一个不错的选择,它可以保护丢失或被盗设备上的数据。

Android 有两种 设备加密方法 :全盘加密和文件加密 。全盘加密 是在Android 4.4 引入的 ,并在 Android 5.0 中默认打开。它会将 /data 分区的用户数据操作加密 / 解密,对性能会有一定的影响,但是新版本的芯片都会在硬件中提供直接支持。

我们知道,基于文件系统的加密,如果设备被解锁了,加密也就没有用了。所以 Android 7.0 增加了 基于文件的加密 。在这种加密模式下,将会给每个文件都分配一个必须用用户的 passcode 推导出来的密钥。特定的文件被屏幕锁屏之后,直到用户下一次解锁屏幕期间都不能访问。

我想说的是,设备加密方法对应用程序来说是透明的,它保证我们读取到的是解密后的数据。对于应用程序特别敏感的数据,我们也需要采用 RSA、AES、chacha20 等常用方式做进一步的存储加密。

常见的数据存储方法

Android 为我们提供了很多种持久化存储的方案,在具体介绍它们之前,你需要先问一下自己,什么是存储?

在我看来,存储就是把特定的数据结构转化成可以被记录和还原的格式,这个数据格式可以是二进制的,也可以是 XML、JSON、Protocol Buffer 这些格式。

对于闪存来说,一切归根到底还是二进制的,XML、JSON 它们只是提供了一套通用的二进制编解码格式规范。既然有那么多存储的方案,那我们在选择数据存储方法时,一般需要考虑哪些关键要素呢 ?

1. 关键要素

2. 存储选项

总的来说,我们需要结合应用场景选择合适的数据存储方法。那 Android 为应用开发者提供了哪些存储数据的方法呢?你可以参考存储选项,综合来看,有下面几种方法。

  • SharedPreferences
  • ContentProvider
  • 文件
  • 数据库

第一,SharedPreferences 的使用。

SharedPreferences 是 Android 中比较常用的存储方法,它可以用来存储一些比较小的键值对集合。

虽然 SharedPreferences 使用非常简便,但也是我们诟病比较多的存储方法。它的性能问题比较多,我可以轻松地说出它的“七宗罪”。

  • 跨进程不安全。由于没有使用跨进程的锁,就算使用MODE_MULTI_PROCESS,SharedPreferences 在跨进程频繁读写有可能导致数据全部丢失。根据线上统计,SP 大约会有万分之一的损坏率。
  • 加载缓慢。SharedPreferences 文件的加载使用了异步线程,而且加载线程并没有设置线程优先级,如果这个时候主线程读取数据就需要等待文件加载线程的结束。这就导致出现主线程等待低优先级线程锁的问题,比如一个 100KB 的 SP 文件读取等待时间大约需要 50~100ms,我建议提前用异步线程预加载启动过程用到的 SP 文件。
  • 全量写入。无论是调用 commit() 还是 apply(),即使我们只改动其中的一个条目,都会把整个内容全部写到文件。而且即使我们多次写入同一个文件,SP 也没有将多次修改合并为一次,这也是性能差的重要原因之一。
  • 卡顿。由于提供了异步落盘的 apply 机制,在崩溃或者其他一些异常情况可能会导致数据丢失。所以当应用收到系统广播,或者被调用 onPause 等一些时机,系统会强制把所有的 SharedPreferences 对象数据落地到磁盘。如果没有落地完成,这时候主线程会被一直阻塞。这样非常容易造成卡顿,甚至是 ANR,从线上数据来看 SP 卡顿占比一般会超过 5%。

PS :可以参考 彻底搞懂 SharePreferences  

坦白来讲,系统提供的 SharedPreferences 的应用场景是用来存储一些非常简单、轻量的数据。我们不要使用它来存储过于复杂的数据,例如 HTML、JSON 等。而且 SharedPreference 的文件存储性能与文件大小相关,每个 SP 文件不能过大,我们不要将毫无关联的配置项保存在同一个文件中,同时考虑将频繁修改的条目单独隔离出来。

对系统提供的 SharedPreferences 的小修小补虽然性能有所提升,但是依然不能彻底解决问题。基本每个大公司都会自研一套替代的存储方案,比如微信最近就开源了 MMKV

PS :对于 MMKV  我写过demo ,但是并没有使用到项目中 ,最近在考虑使用 MMKV  。

下面是 MMKV 对于 SharedPreferences 的“六要素”对比。

PS :可以参考 MMKV 的  实现原理 和 性能检测报告 。里面都是一些很优秀的思路 ,例如 利用文件锁保证跨进程安全 、使用 mmap 保证数据不丢失 ,选用性能和存储空间更好的 Protocol Buffer 代替 XML、支持增量更新等。

根据 I/O 优化的分析,对于频繁修改的配置使用 mmap 的确非常合适,使用者不用去理解 apply() 和 commit() 的差别,也不用担心数据的丢失。同时,我们也不需要每次都提交整个文件,整体性能会有很大提升。

I/O 可以参考  I/O 知识 (自家观众号)

END、 待续

PS :来源自 极客时间 Aandroid 开发高手课

链接 : http://gk.link/a/10eHG

本篇文章同步更新到公众号 SuperMaxs 。

Android 性能优化系列之 —— 存储优化(3)相关推荐

  1. Android性能优化系列之内存优化

    在Java中,内存的分配是由程序完成的,而内存的释放是由垃圾收集器(Garbage Collection,GC)完成的,程序员不需要通过调用函数来释放内存,但也随之带来了内存泄漏的可能,上篇博客,我介 ...

  2. Android性能优化系列:启动优化

    文章目录 1 应用启动类型 1.1 冷启动 1.2 温启动 1.3 热启动 2 查看启动耗时 2.1 adb命令查看 2.2 Logcat Displayed查看启动耗时 2.3 手动记录启动耗时 2 ...

  3. Android性能优化系列之电量优化

    电量消耗的计算与统计是一件麻烦而且矛盾的事情,记录电量消耗本身也是一个费电量的事情,随着Android开的性能要求越来越高,电量的优化,也显得格外重要,一个耗电的应用,用户肯定会毫不犹豫的进行卸载,所 ...

  4. Android性能优化系列之渲染优化

    众所周知的Android系统每隔16ms重新绘制一次activity,也就是说你的app必须在16ms内完成屏幕刷新的所有逻辑操作,这样才能达到60帧/s.而用户一般所看到的卡顿是由于Android的 ...

  5. Android性能优化系列之布局优化,Android程序员校招蚂蚁金服

    25 26 rInflate方法关键代码 void rInflate(XmlPullParser parser, View parent, Context context, AttributeSet ...

  6. 你想要的Android性能优化系列:启动优化 !

    文章目录 一.概述 二.应用启动流程介绍 三.优化核心思想 四.时间检测 4.1 Displayed 4.2 adb shell 4.3 reportFullyDrawn() 4.4 代码打点 4.5 ...

  7. 抖音 Android 性能优化系列:启动优化实践

    动手点关注 干货不迷路 

  8. PLSQL_性能优化系列04_Oracle Optimizer优化器

    2014-09-25 Created By BaoXinjian 一.摘要 1. Oracle优化器介绍 本文讲述了Oracle优化器的概念.工作原理和使用方法,兼顾了Oracle8i.9i以及最新的 ...

  9. Android优化系列之ListView优化老生常谈

    本文内容:adapter,listview的优化,RecycleBi,google大会推荐优化, 实现ListView的过程,Adapter起到了至关重要的作用,不仅仅因为getview()方法.那么 ...

最新文章

  1. CentOS下Docker 安装
  2. 通过脚本禁用域内XP自带防火墙(附收集报告功能)
  3. WinAPI: CloseFigure
  4. Catboost原文解读
  5. python修复不了_如何修复Python代码?
  6. pick王菊?作为“菊外人”的程序员能做点什么?
  7. linux分区理解整理
  8. 使用MOE进行药效团建模与分析
  9. Spring 定时任务
  10. sikuli python java_从命令行运行sikulix 1.1.4 python脚本
  11. Python数据结构与算法(2.3)——链表
  12. unity设置一个物体是另一个物体的子物体
  13. oppo(不root)手机查看万能钥匙破解的wifi密码实例
  14. 单片机c语言6种开方,单片机快速开平方的算法
  15. c# FlexCell自动换行
  16. 通过SMART法则进行网站策划
  17. c语言飞机源代码,C语言写的飞机源码
  18. QString汉字个数检测
  19. [LCT刷题][连通性维护] P3950 部落冲突
  20. nginx 如何查看访问ip和对应访问路径

热门文章

  1. 摄影光学与镜头pdf_网络照相与摄像 PDF 扫描版[42M]
  2. 如何成功的在应聘中使用英语
  3. 《智慧书》格言61-70
  4. win10 wubi linux,迁移Wubi安装的ubuntu到Win10纯净版
  5. java毕业生设计学生宿舍管理系统计算机源码+系统+mysql+调试部署+lw
  6. 名编辑电子杂志大师教程 | 如何使用名编辑上传功能?
  7. 数据洞察——第八期魅族技术开放日现场纪实
  8. EXCEL隔行选取操作
  9. 定制婴儿胚胎,基因筛选天才?这家美国公司想“逆天而行”?
  10. Python加解密库——pycrypto(pycryptodome)