返回
源码角度剖析Glide4缓存
Android
2023-10-09 12:12:28
Glide是Android平台上最受欢迎的图片加载库之一,它提供了强大的缓存机制来优化图片加载性能。Glide的缓存机制分为三级:内存缓存、磁盘缓存和网络缓存。
内存缓存是Glide中最快的缓存层,它将最近加载的图片存储在内存中,以便下次加载时可以直接从内存中读取。磁盘缓存是Glide的第二层缓存,它将图片存储在磁盘上,以便在内存缓存中找不到图片时从磁盘中加载。网络缓存是Glide的第三层缓存,它将图片存储在网络上,以便在磁盘缓存中找不到图片时从网络上加载。
Glide使用EngineKey来管理缓存。EngineKey是缓存的唯一标识符,它包含了图片的URL、图片的尺寸、图片的格式等信息。当Glide需要加载一张图片时,它会首先检查内存缓存中是否有这张图片。如果没有,则会检查磁盘缓存中是否有这张图片。如果没有,则会从网络上加载这张图片。当Glide将图片加载到内存缓存或磁盘缓存中时,它会将EngineKey作为缓存的唯一标识符。这样,当Glide下次需要加载这张图片时,它就可以直接使用EngineKey来查找缓存。
Glide的缓存机制可以显著提高图片加载性能。通过使用内存缓存、磁盘缓存和网络缓存,Glide可以避免重复加载相同的图片,从而减少网络流量和提高加载速度。
下面是Glide缓存机制的源码实现:
public class EngineKeyFactory {
public EngineKey buildKey(Key signature, WidthHeightOptions widthHeightOptions, Map<Class<?>, Transformation<?>> transformations) {
return new EngineKey(signature, widthHeightOptions, transformations);
}
}
public class EngineKey {
private final Key signature;
private final WidthHeightOptions widthHeightOptions;
private final Map<Class<?>, Transformation<?>> transformations;
public EngineKey(Key signature, WidthHeightOptions widthHeightOptions,
Map<Class<?>, Transformation<?>> transformations) {
this.signature = signature;
this.widthHeightOptions = widthHeightOptions;
this.transformations = transformations;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
EngineKey engineKey = (EngineKey) o;
if (!signature.equals(engineKey.signature)) return false;
if (!widthHeightOptions.equals(engineKey.widthHeightOptions)) return false;
return transformations.equals(engineKey.transformations);
}
@Override
public int hashCode() {
int result = signature.hashCode();
result = 31 * result + widthHeightOptions.hashCode();
result = 31 * result + transformations.hashCode();
return result;
}
}
public class GlideBitmapDecoder implements ResourceDecoder<GlideUrl, Bitmap> {
@Override
public Resource<Bitmap> decode(GlideUrl source, int width, int height, Options options)
throws IOException {
SourceFetcher fetcher = buildSourceFetcher(source, width, height);
return decodeSource(fetcher, width, height, options);
}
protected Resource<Bitmap> decodeSource(SourceFetcher fetcher, int width, int height,
Options options) throws IOException {
InputStream is = fetcher.loadData(priority).getStream();
try {
return decodeSource(is, width, height, options);
} finally {
is.close();
}
}
protected Resource<Bitmap> decodeSource(InputStream is, int width, int height, Options options) {
Bitmap bitmap = BitmapFactory.decodeStream(is, null, options.inBitmap);
return BitmapResource.obtain(bitmap, options.pool);
}
@Override
public boolean handles(GlideUrl source, Options options) {
return true;
}
}
public class SourceDecoder<T, R> implements ResourceDecoder<T, R> {
private final DataFetcherFactory<T, R> dataFetcherFactory;
public SourceDecoder(DataFetcherFactory<T, R> dataFetcherFactory) {
this.dataFetcherFactory = dataFetcherFactory;
}
@Override
public Resource<R> decode(T source, int width, int height, Options options)
throws IOException {
DataFetcher<R> fetcher = dataFetcherFactory.buildDataFetcher(source, width, height, options);
R data = fetcher.loadData(priority).get();
return new SimpleResource<>(data);
}
@Override
public boolean handles(T source, Options options) {
return dataFetcherFactory.handles(source);
}
}
public interface DataFetcher<T> {
DataFetcherResult<T> loadData(Priority priority) throws Exception;
}
public class GlideUrl {
private final String url;
public GlideUrl(String url) {
this.url = url;
}
public String getUrl() {
return url;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GlideUrl glideUrl = (GlideUrl) o;
return url.equals(glideUrl.url);
}
@Override
public int hashCode() {
return url.hashCode();
}
}
public class Request {
private final Object model;
private final RequestListener<R> requestListener;
public Request(Object model, RequestListener<R> requestListener) {
this.model = model;
this.requestListener = requestListener;
}
public Object getModel() {
return model;
}
public RequestListener<R> getRequestListener() {
return requestListener;
}
}
public interface Target {
void onResourceReady(Resource<?> resource, Transition<? super Resource<?>> transition);
void onLoadFailed(@Nullable Drawable errorDrawable);
void onLoadCleared(@Nullable Drawable placeholder);
void getSize(SizeReadyCallback cb);
void removeCallback(SizeReadyCallback cb);
}