在安卓开发中,合理使用缓存机制可以显著提升应用性能、减少网络请求、优化用户体验,缓存的核心目标是将频繁使用的数据存储在本地,避免重复获取或计算。
类型 | 特点 | 适用场景 |
---|---|---|
LruCache |
基于最近最少使用(LRU)算法,自动清理不常用数据 | 频繁访问的小数据(如图片、配置) |
HashMap |
手动管理键值对,需自行控制容量 | 简单数据存储,生命周期短 |
示例:使用 LruCache 缓存图片
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 8); LruCache<String, Bitmap> cache = new LruCache<>(maxMemory); // 存入数据 cache.put("key", bitmap); // 读取数据 Bitmap bitmap = cache.get("key");
类型 | 特点 | 适用场景 |
---|---|---|
内部存储(Internal) | 数据私有,无需申请权限,随应用卸载自动清除 | 小文件存储(如配置文件、日志) |
外部存储(External) | 数据公开,需申请 WRITE_EXTERNAL_STORAGE 权限,可能被系统清理 |
大文件存储(如图片、视频) |
序列化方式 | JSON、Protobuf、XML、自定义二进制格式 | 根据数据结构和性能需求选择 |
示例:写入内部存储文件
File file = new File(context.getFilesDir(), "cache.txt"); try (FileOutputStream fos = new FileOutputStream(file)) { fos.write("cached data".getBytes()); }
类型 | 特点 | 适用场景 |
---|---|---|
SQLite | 轻量级关系型数据库,支持复杂查询,需手动管理表结构 | 结构化数据存储(如用户信息、列表) |
Room | 基于 SQLite 的抽象层,提供编译时校验和流畅的API | 需要类型安全和简化操作的场景 |
ContentProvider | 跨应用数据共享,适合公开数据 | 多模块或多应用间数据交互 |
示例:使用 Room 缓存用户信息
@Entity public class User { @PrimaryKey public int id; public String name; } @Dao public interface UserDao { @Insert(onConflict = OnConflictStrategy.REPLACE) void insert(User user); @Query("SELECT FROM User WHERE id = :id") User getUser(int id); }
特点 | 适用场景 |
---|---|
轻量级键值对存储,支持多种数据类型 | 简单配置项(如用户设置、登录状态) |
示例:存储用户设置
SharedPreferences prefs = context.getSharedPreferences("app_settings", MODE_PRIVATE); prefs.edit().putBoolean("is_logged_in", true).apply();
框架 | 特点 |
---|---|
MMKV | 腾讯开源的键值存储库,性能高,支持多进程共享 |
DiskLruCache | Google 提供的磁盘缓存方案,按文件大小管理缓存,适合图片、文件存储 |
Retrofit + OkHttp | 结合网络请求的缓存(如 HTTP 缓存),自动处理缓存策略 |
策略 | 说明 |
---|---|
时间戳验证 | 为数据添加更新时间,读取时检查是否过期(如 last_update 字段) |
版本号控制 | 为数据添加版本号,更新时递增版本号,客户端根据版本号决定是否更新 |
手动触发更新 | 在特定事件(如用户操作、网络请求成功)后主动刷新缓存 |
问题 | 解决方案 |
---|---|
内存溢出(OOM) | 限制缓存大小(如 LruCache 的 maxSize),及时释放无用数据 |
数据一致性问题 | 使用同步机制(如 synchronized )或原子操作,避免多线程竞争 |
缓存雪崩(大量缓存同时失效) | 为缓存数据设置随机过期时间,避免集中失效 |
解答:
mem_
和 file_
)区分存储位置。 解答:
Transaction
,减少 I/O 次数。 LiveData
和 Flowable
实现异步操作,避免阻塞主