安卓面经_Anroid面经(26/30)缓存机制全解析
牛客高级系列专栏:
安卓(安卓系统开发也要掌握)
- 想通关安卓面试,请看(承诺免费售后答疑):《150道安卓高频面试题目录及答案链接》
- 想通关安卓系统面试,请看:《140道安卓系统Framework面试题目录及答案链接》
- 想进阶安卓开发,请看(承诺免费售后答疑):《Android进阶知识体系解析_15大安卓进阶必备知识点》
- 想了解安卓APP完整开发流程,请看(承诺免费售后答疑):《安卓APP完整开发流程》
- 想掌握安卓App性能优化,请看(承诺免费售后答疑):《安卓性能优化讲解和实战专栏》
- 想掌握Gradle语法和配置,制作Gradle插件,请看(承诺免费售后答疑):《安卓Gradle语法解析和实践大全》
嵌入式
- 想通关嵌入式面试,请看: 《111道嵌入式面试题目录及答案链接》
- 想多掌握几个嵌入式项目,请看:《6个嵌入式项目交流分享(附源码)》
本人是2020年毕业于广东工业大学研究生:许乔丹,有国内大厂CVTE和世界500强企业安卓开发经验,该专栏整理本人对常见安卓高频开发面试题的理解;
网上安卓资料千千万,笔者将继续维护专栏,一杯奶茶价格不止提供答案解析,承诺提供专栏内容免费技术答疑,直接咨询即可。助您提高安卓面试准备效率,为您面试保驾护航!
正文开始⬇
缓存机制在实际工作暂时较少接触,但还是有必要学习一下,面试可能会问到。面试官可能会问:
- 你了解Android中的缓存机制吗?⭐⭐⭐⭐
- LruCache的源码看过吗?⭐⭐⭐
- 还有用过哪些缓存工具?⭐⭐⭐⭐
看完以下的解析,一定可以让面试官眼前一亮。
目录
- 1、Android中的缓存机制
- 2、LruCache的使用
- 2.1 LruCache使用实例
- 2.2 LruCache的实现原理
- 2.3 LruCache源码分析
- 2.3.1 增加缓存对象
- 2.3.2 获取缓存对象
- 3、DiskLruCache
- 4、ASimpleCache
1、Android中的缓存机制
现在大家的流量确实增加了wifi普及率也提高了,但每次请求网络还是会出现网络卡顿和延迟现象,给用户造成不好体验,因此缓存机制还是有必要的。通过缓存策略,我们不需要每次都从网上请求图片或从存储设备中加载图片,这样就极大地提高了图片的加载效率以及用户体验。
相对于数据库的增删改查,缓存机制一般也包括缓存的增加、获取、删除三大功能。我们可以增加和获取所需要的缓存,同时,当缓存空间超过设定值,则会删除一些可能不需要的缓存数据以添加新的缓存数据。
LRU(Least Recently Used)缓存算法应运而生。其核心思想就是当缓存满了,会优先删除最早添加,并且最近使用最少的缓存对象。举个例子,我们依次往缓存里存放了[1-5],共5个数据,此时如果要删除数据,则会按照1-2-3-4-5的顺序删除。但是我们又从缓存区获取了第[2]个对象,那么此时如果要删除数据,则会按照1-3-4-5-2的顺序删除,具体代码可见2.2小节。
采用LRU算法的缓存有两种:LruCache和DisLruCache,前者实现了内存缓存,后者实现了磁盘缓存。当然,说到磁盘缓存,很多人会想到数据库以及Sharedpreference等作持久化处理,这当然是可以的。同时,LruCache和DisLruCache配合起来用效果还会更好。现在先来看看LruCache吧。
2、LruCache的使用
LruCache是Android3.1提供的一个缓存类,也就是Android自带的类,只要import android.util.LruCache 就可以直接使用。LruCache是个泛型类,主要算法原理是把最近使用的对象用强引用(即我们平常使用的对象引用方式)存储在 LinkedHashMap(2.2小节会介绍)中。当缓存满时,把最近最少使用的对象从内存中移除,并提供了get和put方法来完成缓存的获取和添加操作。
2.1 LruCache使用实例
如果需要缓存图片,可以这么写:
int maxMemory = (int) (Runtime.getRuntime().totalMemory() / 1024);
int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight() / 1024;
}
};
一般来说,缓存区的大小建议设置为当前进程可用内存的1/8。接着重新sizeOf()方法以便计算出每张图片的大小。最后要特别注意,申请的缓存区大小和每个缓存对象的大小所用的单位要保持一致。
2.2 LruCache的实现原理
正如第1节所述,LruCache会有一个队列,实现优先删除最早添加,并且最近使用最少的缓存对象。而这个队列就是由LinkedHashMap所维护。LinkedHashMap是由数组+双向链表的数据结构实现的。可以通过以下构造函数指定LinkedHashMap的双向链表是按访问数据还是插入顺序排列。
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
当accessOrder变量为true时,LinkedHashMap为访问顺序,为false时LinkedHashMap为插入顺序。将第1节的例子用代码描述如下:
public void test() {
LinkedHashMap<Integer, Integer> map = new LinkedHashMap<>(0, 0.75f, true);
map.put(1, 1);
map.put(2, 2);
map.put(3, 3);
map.put(4, 4);
map.put(5, 5);
map.get(2);
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
最后打印出来的结果正是 1:1 3:3 4:4 5:5 2:2
其中1是最先添加且最近也没有使用过的变量,则排在第1位,此时需要需要删除缓存对象,则优先删除1。2是最近刚使用过的对象,则排在最后输出,也是最后删除的对象。LinkedHashMap这样的逻辑刚好满足LRU缓存算法的思想。因此可以说LurCache的巧妙实现就是利用了LinkedHashMap的结构特性。
2.3 LruCache源码分析
首先看看LruCache的构造函数
// LruCache.java
public LruCache(int maxSize) {
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
}
this.maxSize = maxSize;
this.map = new LinkedHashMap<K, V>(0, 0.75f, true); //1
}
在[注释1]可以明显看到LruCache正是使用了LinkedHashMap的访问顺序。
2.3.1 增加缓存对象
增加缓存使用put()方法:
// LruCache.java
public final V put(K key, V value) {
// 输入不可为空
if (key == null || value == null) {
throw new NullPointerException("key == nu
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
#提供免费售后答疑!!花一杯奶茶的钱获得安卓面试答疑服务,稳赚不赔# Android发展已经很多年,安卓资料网上千千万,本专栏免费提供专栏内容技术答疑!!私聊当天必回。在阅读过程或者其他安卓学习过程有疑问,都非常欢迎私聊交流。