}
3.EngineKey
An in memory only cache key used to multiplex loads.
用于多路传输加载的仅内存缓存密钥.
EngineKey?key?=
keyFactory.buildKey(
...);
4.loadFromMemory
根据上面load方法提供咱们来看看loadFromMemory()这个是重点;
5.loadFromActiveResources
6.loadFromCache
7.getEngineResourceFromCache
到这里如有还未找到,那就说明该图片未保存至内存缓存中来。咱继续往下走,顺着源码跑。
8.waitForExistingOrStartNewJob
咱弄个简化版
private?<R>?LoadStatus?waitForExistingOrStartNewJob(...)?{
//通过添加和删除加载的回调并通知来管理加载的类
//加载完成时回调。
//咱都没数据肯定没加载完成,这个不管。急着往下看
EngineJob<?>?current?=?jobs.get(key,?onlyRetrieveFromCache);
if?(current?!=?null)?{
current.addCallback(cb,?callbackExecutor);
if?(VERBOSE_IS_LOGGABLE)?{
logWithTimeAndKey("Added?to?existing?load",?startTime,?key);
}
return?new?LoadStatus(cb,?current);
}
//同上,接着向下看
EngineJob<R>?engineJob?=
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
//负责从缓存数据或原始源解码资源的类,看着像,咱看看DecodeJob
//应用转换和代码转换。
DecodeJob<R>?decodeJob?=
decodeJobFactory.build(
...
engineJob);
jobs.put(key,?engineJob);
engineJob.addCallback(cb,?callbackExecutor);
engineJob.start(decodeJob);
if?(VERBOSE_IS_LOGGABLE)?{
logWithTimeAndKey("Started?new?load",?startTime,?key);
}
return?new?LoadStatus(cb,?engineJob);
}
9.DecodeJob
class?DecodeJob<R>
implements?DataFetcherGenerator.FetcherReadyCallback,
Runnable,
Comparable<DecodeJob<?>>,
Poolable?{
}
...
//构造方法有个DiskCacheProvider看着跟磁盘缓存有关咱进去瞅瞅
DecodeJob(DiskCacheProvider?diskCacheProvider,?Pools.Pool<DecodeJob<?>>?pool)?{
this.diskCacheProvider?=?diskCacheProvider;
this.pool?=?pool;
}
...
10.DiskCacheProvider
磁盘缓存实现的入口。
在指定的内存中创建基于{@link com.bumptech.glide.disklrucache.disklrucache}的磁盘缓存。
磁盘缓存目录。
public?class?DiskLruCacheFactory?implements?DiskCache.Factory?{
private?final?long?diskCacheSize;
private?final?CacheDirectoryGetter?cacheDirectoryGetter;
/*?在UI线程外调用接口以获取缓存文件夹。?/
public?interface?CacheDirectoryGetter?{
File?getCacheDirectory();
}
public?DiskLruCacheFactory(final?String?diskCacheFolder,?long?diskCacheSize)?{
this(
new?CacheDirectoryGetter()?{
@Override
public?File?getCacheDirectory()?{
return?new?File(diskCacheFolder);
}
},
diskCacheSize);
}
public?DiskLruCacheFactory(
final?String?diskCacheFolder,?final?String?diskCacheName,?long?diskCacheSize)?{
this(
new?CacheDirectoryGetter()?{
@Override
public?File?getCacheDirectory()?{
return?new?File(diskCacheFolder,?diskCacheName);
}
},
diskCacheSize);
}
/**
*使用此构造函数时,将调用{@link?CacheDirectoryGetter#getCacheDirectory()}
*UI线程,允许在不影响性能的情况下进行I/O访问。
*在UI线程外调用@param?cacheDirectoryGetter接口以获取缓存文件夹。
*@param?diskCacheSize?LRU磁盘缓存所需的最大字节大小。
*/
//?Public?API.
@SuppressWarnings("WeakerAccess")
public?DiskLruCacheFactory(CacheDirectoryGetter?cacheDirectoryGetter,?long?diskCacheSize)?{
this.diskCacheSize?=?diskCacheSize;
this.cacheDirectoryGetter?=?cacheDirectoryGetter;
}
@Override
public?DiskCache?build()?{
File?cacheDir?=?cacheDirectoryGetter.getCacheDirectory();
if?(cacheDir?==?null)?{
return?null;
}
if?(cacheDir.isDirectory()?||?cacheDir.mkdirs())?{
return?DiskLruCacheWrapper.create(cacheDir,?diskCacheSize);
}
return?null;
}
}
11.DiskCache.Factory
DiskLruCacheFactory实现的接口是什么,咱看看
/*?用于向磁盘缓存写入数据和从磁盘缓存读取数据的接口?/
public?interface?DiskCache?{
/*?用于创建磁盘缓存的接口?/
interface?Factory?{
/*?250?MB?of?cache.?/
int?DEFAULT_DISK_CACHE_SIZE?=?250??1024??1024;
String?DEFAULT_DISK_CACHE_DIR?=?"image_manager_disk_cache";
/*?返回新的磁盘缓存,如果无法创建磁盘缓存,则返回{@code?null}/
@Nullable
DiskCache?build();
}
/*?向磁盘缓存中的密钥实际写入数据的接口?/
interface?Writer?{
/**
*将数据写入文件
*如果写入操作应中止,则返回false。
*@param?file写入程序应写入的文件。
*/
boolean?write(@NonNull?File?file);
}
/**
*获取给定键处的值的缓存。
*/
@Nullable
File?get(Key?key);
/**
*@param?key要写入的密钥。
*@param?writer一个接口,该接口将在给定密钥输出流的情况下写入数据。
*/
void?put(Key?key,?Writer?writer);
/**
*?从缓存中删除键和值。.
*/
@SuppressWarnings("unused")
void?delete(Key?key);
/*?Clear?the?cache.?/
void?clear();
}
磁盘缓存写入和读取的接口有了,那其他相关联的源码找到试着理解也是没问题的,再多找就乱了。
LRU是什么
LRU是近期最少使用的算法(缓存淘汰算法),它的核心思想是当缓存满时,会优先淘汰那些近期最少使用的缓存对象。采用LRU算法的缓存有两种:LrhCache和DisLruCache,分别用于实现内存缓存和硬盘缓存,其核心思想都是LRU缓存算法。
LruCache的核心思想很好理解,就是要维护一个缓存对象列表,其中对象列表的排列方式是按照访问顺序实现的,即一直没访问的对象,将放在队尾,即将被淘汰。而最近访问的对象将放在队头,最后被淘汰。
内存缓存的LRU
/*?An?LRU?in?memory?cache?for?{@link?com.bumptech.glide.load.engine.Resource}s.?/
public?class?LruResourceCache?extends?LruCache<Key,?Resource<?>>?implements?MemoryCache?{
private?ResourceRemovedListener?listener;
/**
*LruResourceCache的构造函数。
*@param?size内存缓存可以使用的最大字节大小。
*/
public?LruResourceCache(long?size)?{
super(size);
}
@Override
public?void?setResourceRemovedListener(@NonNull?ResourceRemovedListener?listener)?{
【Android 详细知识点思维脑图(技能树)】
我个人是做Android开发,已经有十来年了,目前在某创业公司任职CTO兼系统架构师。虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。
这里附上上述的面试题相关的几十套字节跳动,京东,小米,腾讯、头条、阿里、美团等公司19年的面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。
由于篇幅有限,这里以图片的形式给大家展示一小部分。
详细整理在GitHub可以见;
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
最后,赠与大家一句话,共勉!
标签: