在分析异步加载逻辑前,先了解一些相关的类,了解了这些类对后面阅读加载过程会更加轻松
Registry
Glide支持加载格式非常多,into方法可以传入String,File,Uri,Integer等等,加载成功后输出的格式也齐全,asBitmap,asFile,asGif。那么Glide是如何灵活适配这些加载配置的,答案都在Registry里面。
Registry相当于一个注册表,Glide默认已经注册了一大批的配置,初始化和注册配置位置在Glide的构建方法里
Glide(...) {
...
registry = new Registry();
registry.register(new DefaultImageHeaderParser());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
registry.register(new ExifInterfaceImageHeaderParser());
}
List<ImageHeaderParser> imageHeaderParsers = registry.getImageHeaderParsers();
ByteBufferGifDecoder byteBufferGifDecoder =
new ByteBufferGifDecoder(context, imageHeaderParsers, bitmapPool, arrayPool);
ResourceDecoder<ParcelFileDescriptor, Bitmap> parcelFileDescriptorVideoDecoder =
VideoDecoder.parcel(bitmapPool);
Downsampler downsampler =
new Downsampler(
registry.getImageHeaderParsers(), resources.getDisplayMetrics(), bitmapPool, arrayPool);
ResourceDecoder<ByteBuffer, Bitmap> byteBufferBitmapDecoder;
ResourceDecoder<InputStream, Bitmap> streamBitmapDecoder;
...
}
里面的配置代码比较多,就不展示全了。除了默认的配置,我们还可以自定义配置。例如我们要适配Okhttp,可以继承AppGlideModule,在registerComponents方法添加。其实第一章分析Glide初始化时已经提及过Registry,忘记的同学可以回头看看
public void registerComponents(Context context, Glide glide,Registry registry) {
//注册Okhttp
registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(client));
}
接下来我们详细看看Registry里面注册的是什么
可以看到Registry下细分了各种类型
ModelLoaderRegistry
上面okhttp的注册就是注册到这个类里面
public <Model, Data> Registry replace(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
modelLoaderRegistry.replace(modelClass, dataClass, factory);
return this;
}
- modelClass,就是对应into传递进来的值
- dataClass,okhttp这里传递进来的是inputStream,可以理解为输出的数据类型
- ModelLoaderFactory,生成modelLoader的工厂,工厂build方法有个MultiModelLoaderFactory的入参,平时加载网络图片传递的model是String,但okhttp注册的是GlideUrl,它们是怎么匹配上的。逻辑在MultiModelLoaderFactory生成了MultiModelLoader做了装换,这里就不详细分析了,有兴趣的可以深入看看
ModelLoader
public interface ModelLoader<Model, Data> {
class LoadData<Data> {
public final Key sourceKey;
public final List<Key> alternateKeys;
public final DataFetcher<Data> fetcher;
public LoadData(@NonNull Key sourceKey, @NonNull DataFetcher<Data> fetcher) {
this(sourceKey, Collections.<Key>emptyList(), fetcher);
}
public LoadData(Key sourceKey, List<Key> alternateKeys,DataFetcher<Data> fetcher) {
this.sourceKey = Preconditions.checkNotNull(sourceKey);
this.alternateKeys = Preconditions.checkNotNull(alternateKeys);
this.fetcher = Preconditions.checkNotNull(fetcher);
}
}
@Nullable
LoadData<Data> buildLoadData(Model model, int width, int height, Options options);
boolean handles(@NonNull Model model);
}
- ModelLoader的主要作用是为了创建内部类LoadData,而handles方法是判断是否适配加载的model,如果匹配才会走下一步buildLoadData创建loadData
- loadData包含key和DataFetcher,一般key都是ObjectKey,只是简单的包装一下model。而DataFetcher是真正实现加载的类,将modelClass执行加载,输出dataClass
DataFetcher
public interface DataFetcher<T> {
interface DataCallback<T> {
void onDataReady(@Nullable T data);
void onLoadFailed(@NonNull Exception e);
}
void loadData(@NonNull Priority priority, @NonNull DataCallback<? super T> callback);
void cleanup();
void cancel();
Class<T> getDataClass();
@NonNull
DataSource getDataSource();
}
- 定义了CallBack,分别是加载成功和失败,泛型T就是DataClass,所以okhttp返回的是InputStream
- loadData实现加载的方法,priority是RequestBuilder设置的
- cleanup是做释放操作的,例如关闭InputSteam
- DataSource枚举定义图片的来源,可以是网络,本地资源,磁盘缓存
其他注册表
- ResourceDecoderRegistry - 将DataClass解码,例如InputStream流读取,生成Bitmap。输出的类就是RequestBuilder设置的resourceClass
- TranscoderRegistry - 转换成as方法设置的资源类型,对应的就是RequestBuilder设置的resourceClass转换成transcodeClass,这两个class类RequestBuilder都支持个性化配置
- EncoderRegistry - 将图片数据写入到File文件
- ResourceEncoderRegistry - 图片写入File的策略,用于DiskCacheStrategy磁盘缓存策划判断是否支持
LoadPath
public class LoadPath<Data, ResourceType, Transcode>
抽象定义出注册表多种配置组合出多种加载路线。这个路线是指DataFetcher加载输出DataClass后的路线,三个泛型分别对应分别对应上面的注册表分析,ResourceDecoderRegistry 对应DataClass转换成ResourceType过程,TranscoderRegistry对应ResourceType转换成ResourceType过程。
DiskCacheStrategy
public abstract class DiskCacheStrategy {
public abstract boolean isDataCacheable(DataSource dataSource);
public abstract boolean isResourceCacheable(
boolean isFromAlternateCacheKey, DataSource dataSource, EncodeStrategy encodeStrategy);
public abstract boolean decodeCachedResource();
public abstract boolean decodeCachedData();
}
定义磁盘缓存策略。
- DataCache指原始未变换过的资源缓存,ResourceCache则是已变换过的资源缓存。
- 四个方法都是返回boolean,isCacheable作用是判断是否可以缓存内存图片到磁盘,decodeCached则是判断是否可以读取磁盘文件到内存