glide 默认RGB_565,如果想要用ARGB_8888,怎么解决?
1。可以创建一个新的GlideModule将Bitmap格式转换到ARGB_8888:
Glide.with().load(url).into(imageview); 如何将一张图片展示在imageview上的?
网络请求的在哪边执行的?HttpUrlFetcher loaddata() :返回inputStream
2.Engine的load()方法当中,这里构建了一个EngineJob,它的主要作用就是用来开启线程的,为后面的异步加载图片做准备。
EngineJob的onResourceReady()方法,用Handler发出了一条MSG_COMPLETE消息,那么在MainThreadCallback的handleMessage()方法中就会收到这条消息。从这里开始,所有的逻辑又回到主线程当中进行了,因为很快就需要更新UI了。
GLide内存缓存机制:LruCache 和弱引用 WeakReference
这样也就实现了正在使用中的图片使用弱引用来进行缓存,不在使用中的图片使用LruCache来进行缓存的功能。
这就是Glide内存缓存的实现原理。
使用Glide加载图片时候,默认情况下不会将原始的图片展示,而是会对图片压缩转换后,从硬盘缓存取出转换后的图片。
硬盘缓存的实现:
LruCache算法,google提供的工具DiskLruCache,Glide是实现自己的DiskLruCache工具类,但是基本原理差不多。
Glide
GlideFromCache() 默认先从缓存读取,读取失败,才会decodeFromSource();
decodeFromCache()方法的源码:
这里会先去调用DecodeJob的decodeResultFromCache()方法来获取缓存,如果获取不到,会再调用decodeSourceFromCache()方法获取缓存,这两个方法的区别其实就是DiskCacheStrategy.RESULT和DiskCacheStrategy.SOURCE这两个参数的区别
decodeResultFromCache 调用 loadFromCache(resultKey);
decodeSourceFromCache 调用了loadFromCache(resultKey.getOriginalKey());
接下来看下loadFromCache源码:
private Resource<T> loadFromCache(Key key) throws IOException {
File cacheFile = diskCacheProvider.getDiskCache().get(key);
if (cacheFile == null) {
return null;
}
Resource<T> result = null;
try {
result = loadProvider.getCacheDecoder().decode(cacheFile, width, height);
} finally {
if (result == null) {
diskCacheProvider.getDiskCache().delete(key);
}
}
return result;
}
getDiskCache()即Glide自己编写的DiskLruCache 工具类实例,然后调用get()得到硬盘缓存文件。至此,将硬盘缓存读取的源码的就分析完了,接下来是硬盘缓存在哪里写入的?
刚才已经分析过了,在没有缓存的情况下,会调用decodeFromSource()方法来读取原始图片。t这个方法2句代码:
public Resource<Z> decodeFromSource() throws Exception {
Resource<T> decoded = decodeSource();
return transformEncodeAndTranscode(decoded);
}
具体实现decodeSource():
private Resource<T> decodeSource() throws Exception {
Resource<T> decoded = null;
try {
long startTime = LogTime.getLogTime();
final A data = fetcher.loadData(priority);
if (isCancelled) {
return null;
}
decoded = decodeFromSourceData(data);
} finally {
fetcher.cleanup();
}
return decoded;
}
private Resource<T> decodeFromSourceData(A data) throws IOException {
final Resource<T> decoded;
if (diskCacheStrategy.cacheSource()) {
decoded = cacheAndDecodeSourceData(data);
} else {
long startTime = LogTime.getLogTime();
decoded = loadProvider.getSourceDecoder().decode(data, width, height);
}
return decoded;
}
private Resource<T> cacheAndDecodeSourceData(A data) throws IOException {
long startTime = LogTime.getLogTime();
SourceWriter<A> writer = new SourceWriter<A>(loadProvider.getSourceEncoder(), data);
diskCacheProvider.getDiskCache().put(resultKey.getOriginalKey(), writer);
startTime = LogTime.getLogTime();
Resource<T> result = loadFromCache(resultKey.getOriginalKey());
return result;
}
上面的代码先调用fetcher的loadData()方法读取图片数据,decodeFromSourceData()对图片解码;判断是否允许缓存原始图片,允许就调用cacheAndDecodeSourceData();而在此方法中调用getDiskCache()获取DiskLruCache 实例,然后调用put()写入硬盘缓存,注意这里是缓存的key=resultKey.getOriginalKey();
使用transformEncodeAndTranscode()方法,将图片转换后缓存到磁盘;来看看转换过后的图片缓存是怎么写入的:
调用transform()方法来对图片进行转换,然后在writeTransformedToCache()方法中将转换过后的图片写入到硬盘缓存中,调用的同样是DiskLruCache实例的put()方法,不过这里用的缓存Key是resultKey。
高级技巧:
- DiskCacheStrategy.NONE 什么都不缓存,就像刚讨论的那样
- DiskCacheStrategy.SOURCE 仅仅只缓存原来的全分辨率的图像。在我们上面的例子中,将会只有一个 1000x1000 像素的图片
- DiskCacheStrategy.RESULT 仅仅缓存最终的图像,即,降低分辨率后的(或者是转换后的)
- DiskCacheStrategy.ALL 缓存所有版本的图像(默认行为)
网友评论