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

当context是Activity时,每个页面都会被添加一个空fragment,由空fragment持有页面级别RequestManager

注意:如果with发生在子线程,不管context是谁,都返回应用级别RequestManager单例。

发散:添加空fragment来感知页面生命周期的思想,在Lifecycle的实现中也可以看到,见ReportFragmentinjectIfNeededIn方法。(不过这个方法在Lifecycle的2.2.0版本中有所改动,Android 10开始的设备改成了使用Application.ActivityLifecycleCallbacks来感知,感兴趣可以康康)

至此,我们根据存款context买到了心仪的车RequestManager,下面开始上牌~

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

load:上牌

load方法得到了一个RequestBuilder图片请求构建器,见名知意猜一下,是用来创建图片请求的,

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

class RequestManager implements ComponentCallbacks2, LifecycleListener, ModelTypes<RequestBuilder<Drawable>> { RequestBuilder<Drawable> load(String string) { return asDrawable().load(string); } RequestBuilder<Drawable> asDrawable() { //需要加载的类型为Drawable return as(Drawable.class); } <ResourceType> RequestBuilder<ResourceType> as(Class<ResourceType> 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,

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

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

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

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

最后

为了方便有学习需要的朋友,我把资料都整理成了视频教程(实际上比预期多花了不少精力),由于篇幅有限,都放在了我的GitHub上,点击即可免费获取!

Androidndroid架构视频+BAT面试专题PDF+学习笔记

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

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

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

无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,没有人能随随便便成功。

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

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

无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,没有人能随随便便成功。

加油,共勉。

  • 22
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值