【Android】Glide模块工作原理
Glide模块工作原理
每个Glide模块包含一个Decoder,和一个Transcoder
Decoder负责将DataSource转换为对应的Resource
Transcoder负责将对应的Resource,转换为Drawable
GlideModule示例
这里以SVG为例,展示下GlideModule是如何定义的
class SvgDecoder : ResourceDecoder<InputStream, SVG> {
override fun handles(source: InputStream, options: Options): Boolean {
return true
}
override fun decode(
source: InputStream, width: Int, height: Int, options: Options
): Resource<SVG>? {
try {
val svg = SVG.getFromInputStream(source)
if (width != Target.SIZE_ORIGINAL)
svg.documentWidth = width.toFloat()
if (height != Target.SIZE_ORIGINAL)
svg.documentHeight = height.toFloat()
return SimpleResource(svg)
} catch (e: Throwable) {
return null
}
}
}
class SvgTranscoder : ResourceTranscoder<SVG, PictureDrawable> {
override fun transcode(
toTranscode: Resource<SVG>, options: Options
): Resource<PictureDrawable> {
val svg = toTranscode.get()
val picture = svg.renderToPicture()
val drawable = PictureDrawable(picture)
return SimpleResource(drawable)
}
}
@GlideModule
class SvgLibraryGlideModule : LibraryGlideModule() {
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
registry.register(SVG::class.java, PictureDrawable::class.java, SvgTranscoder())
registry.append(InputStream::class.java, SVG::class.java, SvgDecoder())
}
}
Decode流程
Glide的加载原理,是采用HitTest的方法
轮询所有注册的Decoder,挨个尝试解码DataSource
如果解码成功,则视为该Decoder对应的Resource
再找到Decoder对应的Transcoder,将对应的Resource转为Drawable
这样,便可以将对应资源加载到ImageView当中了
class DecodePath {
private Resource<ResourceType> decodeResourceWithList(
DataRewinder<DataType> rewinder,
int width,
int height,
Options options,
List<Throwable> exceptions
) {
Resource<ResourceType> result = null;
// hit test decoder
for (int i = 0, size = decoders.size(); i < size; i++) {
ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);
try {
DataType data = rewinder.rewindAndGet();
if (decoder.handles(data, options)) {
data = rewinder.rewindAndGet();
result = decoder.decode(data, width, height, options);
}
} catch (Throwable e) {
Log.v(TAG, "Failed to decode data for " + decoder, e);
exceptions.add(e);
}
if (result != null) {
break;
}
}
// hit nothing
if (result == null) {
throw new GlideException(failureMessage, new ArrayList<>(exceptions));
}
return result;
}
}
Glide日志分析
以下报错日志可以看出来,Glide逐个尝试了每个Decoder
以及每个Decoder的解码过程,如果成功,最终都将解出Drawable
Cause (1 of 4): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{FileInputStream->GifDrawable->Drawable}
Cause (2 of 4): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{FileInputStream->Bitmap->Drawable}
Cause (3 of 4): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{FileInputStream->BitmapDrawable->Drawable}
Cause (4 of 4): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{FileInputStream->SVG->Drawable}