第1章 存储基础:Android存储体系概览
各位同学,咱们今天聊聊Android存储。说实话,我见过太多开发者在存储上栽跟头了。有人把大文件往内部存储一丢,结果App体积暴涨;有人搞不清内部存储和外部存储的区别,上线后用户反馈文件丢了……嗯,这些坑我都踩过。
所以第一章,咱们先把地基打牢。你想想看,如果连存储体系都搞不清楚,后面谈性能优化就是空中楼阁。
1.1 Android存储体系概览
Android的存储体系,说白了就是一套「数据怎么放、放哪里、怎么取」的规则。我个人习惯把它分成三层来看:
- 应用层:你写的SharedPreferences、Room数据库、文件读写代码
- 框架层:ContentProvider、StorageManager这些系统服务
- 内核层:Linux VFS、具体文件系统(ext4/f2fs)
我在项目中遇到过一个问题:明明用同样的API读写文件,为什么有的手机快有的手机慢?后来追到内核层才发现,不同厂商的文件系统挂载参数不一样。所以你看,搞存储优化,不能只盯着应用层代码。
核心要点:Android存储体系是分层设计的。上层API屏蔽了底层差异,但性能瓶颈往往藏在底层。优化时要有「全局视角」。
1.2 内部存储 vs 外部存储
这个区别,我面试时必问。但很多人答得模棱两可。咱们用一张表说清楚:
| 对比维度 | 内部存储 | 外部存储 |
|---|---|---|
| 路径示例 | /data/data/包名/ | /storage/emulated/0/Android/data/包名/ |
| 访问权限 | 仅本App可访问 | 其他App可读(旧版本)或需SAF(新版本) |
| 卸载时行为 | 全部清除 | 系统会提示用户是否保留 |
| 存储空间 | 受/data分区大小限制 | 受/sdcard分区大小限制,通常更大 |
| 典型用途 | 数据库、SharedPreferences、敏感配置 | 图片缓存、下载文件、日志 |
这里有个坑,我曾经踩过:不要把用户的重要数据放在内部存储的getCacheDir()里。为什么?因为系统空间不足时,会直接清掉缓存目录。我有个项目,用户笔记存在缓存目录,结果手机提示空间不足后,笔记全没了……用户差点把应用商店评分刷到1星。
避坑指南:getFilesDir()存持久数据,getCacheDir()存临时数据。外部存储用getExternalFilesDir(),别用getExternalStorageDirectory()——那个是公共目录,Android 10以后访问受限。
1.3 分区与文件系统介绍
说到分区,很多同学觉得这是系统工程师的事。其实不然。你写的App跑在哪个分区上,直接影响性能。
Android设备常见的分区有:
- /system:只读,放系统镜像。你动不了。
- /data:用户数据分区,内部存储就在这。读写频繁,性能关键。
- /cache:系统缓存分区。现在很多设备已经合并到/data了。
- /sdcard:模拟的外部存储,实际是/data/media的挂载点。
文件系统这块,我重点说说两个:
ext4
老牌文件系统,稳定可靠。Android 4.4之前基本都用它。但有个问题:日志(journal)写放大。每次写数据,先写日志再写数据,小文件操作时性能损耗明显。我在做某社交App的聊天记录存储时,发现大量小消息写入导致卡顿,后来改用f2fs解决了。
f2fs
Flash Friendly File System,三星开发的。专门为闪存优化。它把存储空间分成冷热数据区,减少写放大。从Android 8.0开始,Google推荐厂商用f2fs格式化/data分区。
小技巧:怎么判断手机用的是ext4还是f2fs?adb shell mount | grep /data 看看。如果是f2fs,恭喜你,小文件随机写性能会好很多。但如果是ext4,也别慌,后面章节我会讲怎么优化。
嗯,这里要注意:分区大小直接影响GC(垃圾回收)效率。闪存写入前要先擦除,擦除单位是块(通常4MB)。如果分区剩余空间不足10%,GC会频繁触发,写入速度断崖式下跌。我见过一个极端案例:某App日志文件写满了/data分区,结果整个系统卡成PPT。
1.4 存储路径的选择策略
讲完理论,给点实战建议。我个人习惯这样选路径:
- 数据库、配置、Token → 内部存储 getFilesDir()
- 图片缓存、下载的临时文件 → 外部存储 getExternalCacheDir()
- 用户主动保存的文件(如导出PDF) → 外部存储公共目录(用MediaStore或SAF)
- 日志文件 → 外部存储 getExternalFilesDir("logs")
为什么这样分?说白了就是「谁负责清理」的问题。内部存储的数据,App自己管;外部缓存,系统可以帮忙清;公共目录,用户自己管。责任清晰,不容易出问题。
一句话总结:存储优化从选对路径开始。路径选错了,后面IOPS再高也白搭。
好了,第一章就到这里。下一章咱们聊聊「文件读写性能的微观分析」,我会带你看懂IOPS、吞吐量这些指标,还会分享一个我优化图片加载时发现的「玄学问题」——嗯,其实不是玄学,是文件系统参数没调对。