Android _ 《看完不忘系列》之Glide

implements ComponentCallbacks2, LifecycleListener, ModelTypes<RequestBuilder> {
RequestBuilder load(String string) {
return asDrawable().load(string);
}
RequestBuilder asDrawable() {
//需要加载的类型为Drawable
return as(Drawable.class);
}
RequestBuilder as(Class resourceClass) {
//创建一个请求构建器
return new RequestBuilder<>(glide, this, resourceClass, context);
}
}`

然后跟进asDrawable().load(string)

class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>> implements Cloneable, ModelTypes<RequestBuilder<TranscodeType>> { RequestBuilder<TranscodeType> load(String string) { return loadGeneric(string); } RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) { //只是简单地赋值 this.model = model; isModelSet = true; return this; } }

到这里,我们就完成了上牌,得到了一个RequestBuilder图片请求构建器。没错,上牌就这么简单,毕竟摇号已经够艰难了对吧?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

into:发车

阶段一

来到into了,

class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>> implements Cloneable, ModelTypes<RequestBuilder<TranscodeType>> { ViewTarget<ImageView, TranscodeType> into(ImageView view) { //... BaseRequestOptions<?> requestOptions = this; if (!requestOptions.isTransformationSet() && requestOptions.isTransformationAllowed() && view.getScaleType() != null) { //根据ImageView的ScaleType,来配置参数 switch (view.getScaleType()) { case CENTER_CROP: requestOptions = requestOptions.clone().optionalCenterCrop(); break; case CENTER_INSIDE: requestOptions = requestOptions.clone().optionalCenterInside(); break; //... } } return into( //前面提到,Target是展示图片的载体,这里他封装了ImageView glideContext.buildImageViewTarget(view, transcodeClass),null, requestOptions,Executors.mainThreadExecutor()); } }

继续跟进into重载方法,

class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>> implements Cloneable, ModelTypes<RequestBuilder<TranscodeType>> { <Y extends Target<TranscodeType>> Y into(Y target,RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> options,Executor callbackExecutor) { //... //创建图片请求 Request request = buildRequest(target, targetListener, options, callbackExecutor); //获取Target载体已有的请求 Request previous = target.getRequest(); //如果两个请求等效,并且xxx(先忽略) if (request.isEquivalentTo(previous) && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) { if (!Preconditions.checkNotNull(previous).isRunning()) { //启动异步请求 previous.begin(); } return target; } requestManager.clear(target); //图片载体绑定图片请求,即imageView setTag为request target.setRequest(request); //启动异步请求 requestManager.track(target, request); return target; } }

跟进requestManager.track(target, request)

//RequestManager.java void track(Target<?> target,Request request) { targetTracker.track(target); requestTracker.runRequest(request); } //RequestTracker.java void runRequest(Request request) { requests.add(request); if (!isPaused) { //开启图片请求 request.begin(); } else { request.clear(); //如果处于暂停状态,就把请求存起来,晚些处理 pendingRequests.add(request); } }

到这里,就启动了图片请求,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

阶段二

那么,接下来重点关注的就是request.begin()了,

class SingleRequest<R> implements Request, SizeReadyCallback, ResourceCallback { void begin() { synchronized (requestLock) { //... if (Util.isValidDimensions(overrideWidth, overrideHeight)) { //如果已经有了明确的尺寸,开始加载 onSizeReady(overrideWidth, overrideHeight); } else { //没有的话先去获取尺寸,最终还是走onSizeReady target.getSize(this); } //... } } void onSizeReady(int width, int height) { synchronized (requestLock) { //... //engine.load,传了很多参数 loadStatus = engine.load(glideContext,model, requestOptions.getSignature(), this.width,this.height, requestOptions.getResourceClass(), transcodeClass,priority, requestOptions.getDiskCacheStrategy(), //... this,callbackExecutor); //... } } }

跟进engine.load

class Engine implements EngineJobListener,MemoryCache.ResourceRemovedListener, EngineResource.ResourceListener { <R> LoadStatus load( GlideContext glideContext, //... Executor callbackExecutor) { //... EngineResource<?> memoryResource; synchronized (this) { //从内存加载 memoryResource = loadFromMemory(key, isMemoryCacheable, startTime); if (memoryResource == null) { //如果内存里没有缓存,则加载 return waitForExistingOrStartNewJob( glideContext, model, //... key, startTime); } } cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE); return null; } <R> LoadStatus waitForExistingOrStartNewJob(...) { //... EngineJob<R> engineJob =engineJobFactory.build(...); DecodeJob<R> decodeJob =decodeJobFactory.build(...); jobs.put(key, engineJob); //添加回调,这个cb就是SingleRequest自己,todo1 engineJob.addCallback(cb, callbackExecutor); //engineJob开启decodeJob engineJob.start(decodeJob); return new LoadStatus(cb, engineJob); } }

DecodeJob是一个Runable,看看他的run方法,调用链如下:

DecodeJob.run -> DecodeJob.runWrapped -> DecodeJob.runGenerators ->

SourceGenerator.startNext -> SourceGenerator.startNextLoad ->

MultiModelLoader#MultiFetcher.loadData ->

HttpUrlFetcher.loadData

来到HttpUrlFetcher

class HttpUrlFetcher implements DataFetcher<InputStream> { void loadData(Priority priority, DataCallback<? super InputStream> callback) { try { //获取输入流,没有引入okhttp,则使用HttpURLConnection InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders()); //回调出去 callback.onDataReady(result); } catch (IOException e) { callback.onLoadFailed(e); } finally { } } }

到这里,网络请求就完成了,下面看看图片是怎么设置上去的,前边留了个todo1,

//添加回调,这个cb就是SingleRequest自己,todo1

callback就是SingleRequest,被回调前有一些对象包装、解码操作,暂不深究,来到SingleRequest

class SingleRequest<R> implements Request, SizeReadyCallback, ResourceCallback { void onResourceReady(Resource<?> resource, DataSource dataSource) { Resource<?> toRelease = null; try { synchronized (requestLock) { //... Object received = resource.get(); //... //这里 onResourceReady((Resource<R>) resource, (R) received, dataSource); } } finally { if (toRelease != null) { engine.release(toRelease); } } } void onResourceReady(Resource<R> resource, R result, DataSource dataSource) { //... try { //... //这里,回调给Target载体 target.onResourceReady(result, animation); } finally { } notifyLoadSuccess(); } }

跟进target.onResourceReady,最终来到DrawableImageViewTarget

class DrawableImageViewTarget extends ImageViewTarget<Drawable> { void setResource(Drawable resource) { //ImageView设置图片 view.setImageDrawable(resource); } }

结合阶段一和二,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

终于,汽车发动起来了~

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

with购车load上牌into发车三个环节汇总起来,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可以看到,整个图片加载过程,就是with得到RequestManager,load得到RequestBuilder,然后into开启加载:

创建Request、开启Engine、运行DecodeJob线程、HttpUrlFetcher加载网络数据、回调给载体Target、载体为ImageView设置展示图片。

细枝:补充

线程切换

在子线程下载完图片后,如何回调主线程设置图片?在Executors类里,

private static final Executor MAIN_THREAD_EXECUTOR = new Executor() { //主线程Handler private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable command) { //切回主线程 handler.post(command); } };

调用栈如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

线程池

GlideBuilder类里会初始化一些线程池:

Glide build(Context context) { private GlideExecutor sourceExecutor; //加载图片 private GlideExecutor diskCacheExecutor; //管理磁盘缓存 private GlideExecutor animationExecutor; //管理动画 }

缓存

有内存缓存和磁盘缓存,在Engine.load时会去取,篇幅原因后面单独开篇来写。

webp动图

Fresco支持解析webp动图,Glide不支持,不过已经有了开源的方案,见GitHub - GlideWebpDecoder

选型

FrescoGlide怎么选?

Fresco具有一定侵入性,需要继承SimpleDraweeView

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。

相信它会给大家带来很多收获:

img

当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

  • 无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!!
  • 我希望每一个努力生活的IT工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。

当我们在抱怨环境,抱怨怀才不遇的时候,没有别的原因,一定是你做的还不够好!

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

  • 无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!!
  • 我希望每一个努力生活的IT工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。

当我们在抱怨环境,抱怨怀才不遇的时候,没有别的原因,一定是你做的还不够好!

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 24
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值