当前位置:   article > 正文

Android主流三方库源码分析:Glide,模具项目工程师面试经验_android glide buildloaddata

android glide buildloaddata

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

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

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

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

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注Android)
img

正文

复制代码

3、GlideBuilder#build

@NonNull

Glide build(@NonNull Context context) {

// 创建请求图片线程池sourceExecutor

if (sourceExecutor == null) {

sourceExecutor = GlideExecutor.newSourceExecutor();

}

// 创建硬盘缓存线程池diskCacheExecutor

if (diskCacheExecutor == null) {

diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();

}

// 创建动画线程池animationExecutor

if (animationExecutor == null) {

animationExecutor = GlideExecutor.newAnimationExecutor();

}

if (memorySizeCalculator == null) {

memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();

}

if (connectivityMonitorFactory == null) {

connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();

}

if (bitmapPool == null) {

// 依据设备的屏幕密度和尺寸设置各种pool的size

int size = memorySizeCalculator.getBitmapPoolSize();

if (size > 0) {

// 创建图片线程池LruBitmapPool,缓存所有被释放的bitmap

// 缓存策略在API大于19时,为SizeConfigStrategy,小于为AttributeStrategy。

// 其中SizeConfigStrategy是以bitmap的size和config为key,value为bitmap的HashMap

bitmapPool = new LruBitmapPool(size);

} else {

bitmapPool = new BitmapPoolAdapter();

}

}

// 创建对象数组缓存池LruArrayPool,默认4M

if (arrayPool == null) {

arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSiz eInBytes());

}

// 创建LruResourceCache,内存缓存

if (memoryCache == null) {

memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCa cheSize());

}

if (diskCacheFactory == null) {

diskCacheFactory = new InternalCacheDiskCacheFactory(context);

}

// 创建任务和资源管理引擎(线程池,内存缓存和硬盘缓存对象)

if (engine == null) {

engine =

new Engine(

memoryCache,

diskCacheFactory,

diskCacheExecutor,

sourceExecutor,

GlideExecutor.newUnlimitedSourceExecutor( ),

GlideExecutor.newAnimationExecutor(),

isActiveResourceRetentionAllowed);

}

RequestManagerRetriever requestManagerRetriever =

new RequestManagerRetriever(requestManagerFactory);

return new Glide(

context,

engine,

memoryCache,

bitmapPool,

arrayPool,

requestManagerRetriever,

connectivityMonitorFactory,

logLevel,

defaultRequestOptions.lock(),

defaultTransitionOptions);

}

复制代码

4、Glide#Glide构造方法

Glide(…) {

// 注册管理任务执行对象的类(Registry)

// Registry是一个工厂,而其中所有注册的对象都是一个工厂员工,当任务分发时,

// 根据当前任务的性质,分发给相应员工进行处理

registry = new Registry();

// 这里大概有60余次的append或register员工组件(解析器、编解码器、工厂类、转码类等等组件)

registry

.append(ByteBuffer.class, new ByteBufferEncoder())

.append(InputStream.class, new StreamEncoder(arrayPool))

// 根据给定子类产出对应类型的target(BitmapImageViewTarget / DrawableImageViewTarget)

ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();

glideContext =

new GlideContext(

context,

arrayPool,

registry,

imageViewTargetFactory,

defaultRequestOptions,

defaultTransitionOptions,

engine,

logLevel);

}

复制代码

5、RequestManagerRetriever#get

@NonNull

public RequestManager get(@NonNull Context context) {

if (context == null) {

throw new IllegalArgumentException(“You cannot start a load on a null Context”);

} else if (Util.isOnMainThread() && !(context instanceof Application)) {

// 如果当前线程是主线程且context不是Application走相应的get重载方法

if (context instanceof FragmentActivity) {

return get((FragmentActivity) context);

} else if (context instanceof Activity) {

return get((Activity) context);

} else if (context instanceof ContextWrapper) {

return get(((ContextWrapper) context).getBaseContext());

}

}

// 否则直接将请求与ApplicationLifecycle关联

return getApplicationManager(context);

}

复制代码

这里总结一下,对于当前传入的context是application或当前线程是子线程时,请求的生命周期和ApplicationLifecycle关联,否则,context是FragmentActivity或Fragment时,在当前组件添加一个SupportFragment(SupportRequestManagerFragment),context是Activity时,在当前组件添加一个Fragment(RequestManagerFragment)。

6、GlideApp#with小结
1、初始化各式各样的配置信息(包括缓存,请求线程池,大小,图片格式等等)以及glide对象。
2、将glide请求和application/SupportFragment/Fragment的生命周期绑定在一块。
这里我们再回顾一下with方法的执行流程。

三、load(url)源码详解

1、GlideRequest(RequestManager)#load

return (GlideRequest) super.load(string);

return asDrawable().load(string);

// 1、asDrawable部分

return (GlideRequest) super.asDrawable();

return as(Drawable.class);

// 最终返回了一个GlideRequest(RequestManager的子类)

return new GlideRequest<>(glide, this, resourceClass, context);

// 2、load部分

return (GlideRequest) super.load(string);

return loadGeneric(string);

@NonNull

private RequestBuilder loadGeneric(@Nullable Object model) {

// model则为设置的url

this.model = model;

// 记录url已设置

isModelSet = true;

return this;

}

复制代码

可以看到,load这部分的源码很简单,就是给GlideRequest(RequestManager)设置了要请求的mode(url),并记录了url已设置的状态。

这里,我们再看看load方法的执行流程。

四、into(iv)源码详解

前方预警,真正复杂的地方开始了。

1、RequestBuilder.into

@NonNull

public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {

Util.assertMainThread();

Preconditions.checkNotNull(view);

RequestOptions requestOptions = this.requestOptions;

if (!requestOptions.isTransformationSet()

&& requestOptions.isTransformationAllowed()

&& view.getScaleType() != null) {

// Clone in this method so that if we use this RequestBuilder to load into a View and then

// into a different target, we don’t retain the transformation applied based on the previous

// View’s scale type.

switch (view.getScaleType()) {

// 这个RequestOptions里保存了要设置的scaleType,Glide自身封装了CenterCrop、CenterInside、

// FitCenter、CenterInside四种规格。

case CENTER_CROP:

requestOptions = requestOptions.clone().optionalCenterCrop();

break;

case CENTER_INSIDE:

requestOptions = requestOptions.clone().optionalCenterInside() ;

break;

case FIT_CENTER:

case FIT_START:

case FIT_END:

requestOptions = requestOptions.clone().optionalFitCenter();

break;

case FIT_XY:

requestOptions = requestOptions.clone().optionalCenterInside() ;

break;

case CENTER:

case MATRIX:

default:

// Do nothing.

}

}

// 注意,这个transcodeClass是指的drawable或bitmap

return into(

glideContext.buildImageViewTarget(view, transcodeClass),

/targetListener=/ null,

requestOptions);

}

复制代码

2、GlideContext#buildImageViewTarget

return imageViewTargetFactory.buildTarget(imageView, transcodeClass);

复制代码

3、ImageViewTargetFactory#buildTarget

@NonNull

@SuppressWarnings(“unchecked”)

public ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,

@NonNull Class clazz) {

// 返回展示Bimtap/Drawable资源的目标对象

if (Bitmap.class.equals(clazz)) {

return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);

} else if (Drawable.class.isAssignableFrom(clazz)) {

return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);

} else {

throw new IllegalArgumentException(

"Unhandled class: " + clazz + “, try .as*(Class).transcode(ResourceTranscoder)”);

}

}

复制代码

可以看到,Glide内部只维护了两种target,一种是BitmapImageViewTarget,另一种则是DrawableImageViewTarget,接下来继续深入。

4、RequestBuilder#into

private <Y extends Target> Y into(

@NonNull Y target,

@Nullable RequestListener targetListener,

@NonNull RequestOptions options) {

Util.assertMainThread();

Preconditions.checkNotNull(target);

if (!isModelSet) {

throw new IllegalArgumentException(“You must call #load() before calling #into()”);

}

options = options.autoClone();

// 分析1.建立请求

Request request = buildRequest(target, targetListener, options);

Request previous = target.getRequest();

if (request.isEquivalentTo(previous)

&& !isSkipMemoryCacheWithCompletePreviousReques t(options, previous)) {

request.recycle();

// If the request is completed, beginning again will ensure the result is re-delivered,

// triggering RequestListeners and Targets. If the request is failed, beginning again will

// restart the request, giving it another chance to complete. If the request is already

// running, we can let it continue running without interruption.

if (!Preconditions.checkNotNull(previous).isRunni ng()) {

// Use the previous request rather than the new one to allow for optimizations like skipping

// setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions

// that are done in the individual Request.

previous.begin();

}

return target;

}

requestManager.clear(target);

target.setRequest(request);

// 分析2.真正追踪请求的地方

requestManager.track(target, request);

return target;

}

// 分析1

private Request buildRequest(

Target target,

@Nullable RequestListener targetListener,

RequestOptions requestOptions) {

return buildRequestRecursive(

target,

targetListener,

/parentCoordinator=/ null,

transitionOptions,

requestOptions.getPriority(),

requestOptions.getOverrideWidth(),

requestOptions.getOverrideHeight(),

requestOptions);

}

// 分析1

private Request buildRequestRecursive(

Target target,

@Nullable RequestListener targetListener,

@Nullable RequestCoordinator parentCoordinator,

TransitionOptions<?, ? super TranscodeType> transitionOptions,

Priority priority,

int overrideWidth,

int overrideHeight,

RequestOptions requestOptions) {

// Build the ErrorRequestCoordinator first if necessary so we can update parentCoordinator.

ErrorRequestCoordinator errorRequestCoordinator = null;

if (errorBuilder != null) {

// 创建errorRequestCoordinator(异常处理对象)

errorRequestCoordinator = new ErrorRequestCoordinator(parentCoordinator);

parentCoordinator = errorRequestCoordinator;

}

// 递归建立缩略图请求

Request mainRequest =

buildThumbnailRequestRecursive(

target,

targetListener,

parentCoordinator,

transitionOptions,

priority,

overrideWidth,

overrideHeight,

requestOptions);

if (errorRequestCoordinator == null) {

return mainRequest;

}

Request errorRequest = errorBuilder.buildRequestRecursive(

target,

targetListener,

errorRequestCoordinator,

errorBuilder.transitionOptions,

errorBuilder.requestOptions.getPriority(),

errorOverrideWidth,

errorOverrideHeight,

errorBuilder.requestOptions);

errorRequestCoordinator.setRequests(mainRequest, errorRequest);

return errorRequestCoordinator;

}

// 分析1

private Request buildThumbnailRequestRecursive(

Target target,

RequestListener targetListener,

@Nullable RequestCoordinator parentCoordinator,

TransitionOptions<?, ? super TranscodeType> transitionOptions,

Priority priority,

int overrideWidth,

int overrideHeight,

RequestOptions requestOptions) {

if (thumbnailBuilder != null) {

// Recursive case: contains a potentially recursive thumbnail request builder.

ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);

// 获取一个正常请求对象

Request fullRequest =

obtainRequest(

target,

targetListener,

requestOptions,

coordinator,

transitionOptions,

priority,

overrideWidth,

overrideHeight);

isThumbnailBuilt = true;

// Recursively generate thumbnail requests.

// 使用递归的方式建立一个缩略图请求对象

Request thumbRequest =

thumbnailBuilder.buildRequestRecursive(

target,

targetListener,

coordinator,

thumbTransitionOptions,

thumbPriority,

thumbOverrideWidth,

thumbOverrideHeight,

thumbnailBuilder.requestOptions);

isThumbnailBuilt = false;

// coordinator(ThumbnailRequestCoordinator)是作为两者的协调者,

// 能够同时加载缩略图和正常的图的请求

coordinator.setRequests(fullRequest, thumbRequest);

return coordinator;

} else if (thumbSizeMultiplier != null) {

// Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.

// 当设置了缩略的比例thumbSizeMultiplier(0 ~ 1)时,

// 不需要递归建立缩略图请求

ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);

Request fullRequest =

obtainRequest(

target,

targetListener,

requestOptions,

coordinator,

transitionOptions,

priority,

overrideWidth,

overrideHeight);

RequestOptions thumbnailOptions = requestOptions.clone()

.sizeMultiplier(thumbSizeMultiplier);

Request thumbnailRequest =

obtainRequest(

target,

targetListener,

thumbnailOptions,

coordinator,

transitionOptions,

getThumbnailPriority(priority),

overrideWidth,

overrideHeight);

coordinator.setRequests(fullRequest, thumbnailRequest);

return coordinator;

} else {

// Base case: no thumbnail.

// 没有缩略图请求时,直接获取一个正常图请求

return obtainRequest(

target,

targetListener,

requestOptions,

parentCoordinator,

transitionOptions,

priority,

overrideWidth,

overrideHeight);

}

}

private Request obtainRequest(

Target target,

RequestListener targetListener,

RequestOptions requestOptions,

RequestCoordinator requestCoordinator,

TransitionOptions<?, ? super TranscodeType> transitionOptions,

Priority priority,

int overrideWidth,

int overrideHeight) {

// 最终实际返回的是一个SingleRequest对象(将制定的资源加载进对应的Target

return SingleRequest.obtain(

context,

glideContext,

model,

transcodeClass,

requestOptions,

overrideWidth,

overrideHeight,

priority,

target,

targetListener,

requestListeners,

requestCoordinator,

glideContext.getEngine(),

transitionOptions.getTransitionFactory());

}

复制代码

从上源码分析可知,我们在分析1处的buildRequest()方法里建立了请求,且最多可同时进行缩略图和正常图的请求,最后,调用了requestManager.track(target, request)方法,接着看看track里面做了什么。

5、RequestManager#track

// 分析2

void track(@NonNull Target<?> target, @NonNull Request request) {

// 加入一个target目标集合(Set)

targetTracker.track(target);

requestTracker.runRequest(request);

}

复制代码

6、RequestTracker#runRequest

/**

  • Starts tracking the given request.

*/

// 分析2

public void runRequest(@NonNull Request request) {

requests.add(request);

if (!isPaused) {

// 如果不是暂停状态则开始请求

request.begin();

} else {

request.clear();

if (Log.isLoggable(TAG, Log.VERBOSE)) {

Log.v(TAG, “Paused, delaying request”);

}

// 否则清空请求,加入延迟请求队列(为了对这些请求维持一个强引用,使用了ArrayList实现)

pendingRequests.add(request);

}

}

复制代码

7、SingleRequest#begin

// 分析2

@Override

public void begin() {

if (model == null) {

// model(url)为空,回调加载失败

onLoadFailed(new GlideException(“Received null model”), logLevel);

return;

}

if (status == Status.RUNNING) {

throw new IllegalArgumentException(“Cannot restart a running request”);

}

if (status == Status.COMPLETE) {

onResourceReady(resource, DataSource.MEMORY_CACHE);

return;

}

status = Status.WAITING_FOR_SIZE;

if (Util.isValidDimensions(overrideWidth, overrideHeight)) {

// 当使用override() API为图片指定了一个固定的宽高时直接执行onSizeReady,

// 最终的核心处理位于onSizeReady

onSizeReady(overrideWidth, overrideHeight);

} else {

// 根据imageView的宽高算出图片的宽高,最终也会走到onSizeReady

target.getSize(this);

}

if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)

&& canNotifyStatusChanged()) {

// 预先加载设置的缩略图

target.onLoadStarted(getPlaceholderDrawable());

}

if (IS_VERBOSE_LOGGABLE) {

logV("finished run method in " + LogTime.getElapsedMillis(startTime));

}

}

复制代码

从requestManager.track(target, request)开始,最终会执行到SingleRequest#begin()方法的onSizeReady,可以猜到(因为后面只做了预加载缩略图的处理),真正的请求就是从这里开始的,咱们进去一探究竟~

8、SingleRequest#onSizeReady

// 分析2

@Override

public void onSizeReady(int width, int height) {

stateVerifier.throwIfRecycled();

status = Status.RUNNING;

float sizeMultiplier = requestOptions.getSizeMultiplier();

this.width = maybeApplySizeMultiplier(width, sizeMultiplier);

this.height = maybeApplySizeMultiplier(height, sizeMultiplier);

// 根据给定的配置进行加载,engine是一个负责加载、管理活跃和缓存资源的引擎类

loadStatus = engine.load(

glideContext,

model,

requestOptions.getSignature(),

this.width,

this.height,

requestOptions.getResourceClass(),

transcodeClass,

priority,

requestOptions.getDiskCacheStrategy(),

requestOptions.getTransformations(),

requestOptions.isTransformationRequired(),

requestOptions.isScaleOnlyOrNoTransform(),

requestOptions.getOptions(),

requestOptions.isMemoryCacheable(),

requestOptions.getUseUnlimitedSourceGeneratorsP ool(),

requestOptions.getUseAnimationPool(),

requestOptions.getOnlyRetrieveFromCache(),

this);

}

复制代码

终于看到Engine类了,感觉距离成功不远了,继续~

9、Engine#load

public LoadStatus load(

GlideContext glideContext,

Object model,

Key signature,

int width,

int height,

Class<?> resourceClass,

Class transcodeClass,

Priority priority,

DiskCacheStrategy diskCacheStrategy,

Map<Class<?>, Transformation<?>> transformations,

boolean isTransformationRequired,

boolean isScaleOnlyOrNoTransform,

Options options,

boolean isMemoryCacheable,

boolean useUnlimitedSourceExecutorPool,

boolean useAnimationPool,

boolean onlyRetrieveFromCache,

ResourceCallback cb) {

// 先从弱引用中查找,如果有的话回调onResourceReady并直接返回

EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);

if (active != null) {

cb.onResourceReady(active, DataSource.MEMORY_CACHE);

if (VERBOSE_IS_LOGGABLE) {

logWithTimeAndKey(“Loaded resource from active resources”, startTime, key);

}

return null;

}

// 没有再从内存中查找,有的话会取出并放到ActiveResources(内部维护的弱引用缓存map)里面

EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);

if (cached != null) {

cb.onResourceReady(cached, DataSource.MEMORY_CACHE);

if (VERBOSE_IS_LOGGABLE) {

logWithTimeAndKey(“Loaded resource from cache”, startTime, key);

}

return null;

}

EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);

if (current != null) {

current.addCallback(cb);

if (VERBOSE_IS_LOGGABLE) {

logWithTimeAndKey(“Added to existing load”, startTime, key);

}

return new LoadStatus(cb, current);

}

// 如果内存中没有,则创建engineJob(decodejob的回调类,管理下载过程以及状态)

EngineJob engineJob =

engineJobFactory.build(

key,

isMemoryCacheable,

useUnlimitedSourceExecutorPool,

useAnimationPool,

onlyRetrieveFromCache);

// 创建解析工作对象

DecodeJob decodeJob =

decodeJobFactory.build(

glideContext,

model,

key,

signature,

width,

height,

resourceClass,

transcodeClass,

priority,

diskCacheStrategy,

transformations,

isTransformationRequired,

isScaleOnlyOrNoTransform,

onlyRetrieveFromCache,

options,

engineJob);

// 放在Jobs内部维护的HashMap中

jobs.put(key, engineJob);

// 关注点8 后面分析会用到

// 注册ResourceCallback接口

engineJob.addCallback(cb);

// 内部开启线程去请求

engineJob.start(decodeJob);

if (VERBOSE_IS_LOGGABLE) {

logWithTimeAndKey(“Started new load”, startTime, key);

}

return new LoadStatus(cb, engineJob);

}

public void start(DecodeJob decodeJob) {

this.decodeJob = decodeJob;

// willDecodeFromCache方法内部根据不同的阶段stage,如果是RESOURCE_CACHE/DATA_CACHE则返回true,使用diskCacheExecutor,否则调用getActiveSourceExecutor,内部会根据相应的条件返回sourceUnlimitedExecutor/animationExecutor/sourceExecutor

GlideExecutor executor =

decodeJob.willDecodeFromCache()

? diskCacheExecutor
getActiveSourceExecutor();

executor.execute(decodeJob);

}

复制代码

可以看到,最终Engine(引擎)类内部会执行到自身的start方法,它会根据不同的配置采用不同的线程池使用diskCacheExecutor/sourceUnlimitedExecutor/animationExecutor/sourceExecutor来执行最终的解码任务decodeJob。

10、DecodeJob#run

runWrapped();

private void runWrapped() {

switch (runReason) {

case INITIALIZE:

stage = getNextStage(Stage.INITIALIZE);

// 关注点1

currentGenerator = getNextGenerator();

// 关注点2 内部会调用相应Generator的startNext()

runGenerators();

break;

case SWITCH_TO_SOURCE_SERVICE:

runGenerators();

break;

case DECODE_DATA:

// 关注点3 将获取的数据解码成对应的资源

decodeFromRetrievedData();

break;

default:

throw new IllegalStateException("Unrecognized run reason: " + runReason);

}

}

// 关注点1,完整情况下,会异步依次生成这里的ResourceCacheGenerator、DataCacheGenerator和SourceGenerator对象,并在之后执行其中的startNext()

private DataFetcherGenerator getNextGenerator() {

switch (stage) {

case RESOURCE_CACHE:

return new ResourceCacheGenerator(decodeHelper, this);

case DATA_CACHE:

return new DataCacheGenerator(decodeHelper, this);

case SOURCE:

return new SourceGenerator(decodeHelper, this);

case FINISHED:

return null;

default:

throw new IllegalStateException("Unrecognized stage: " + stage);

}

}

复制代码

11、SourceGenerator#startNext

// 关注点2

@Override

public boolean startNext() {

// dataToCache数据不为空的话缓存到硬盘(第一执行该方法是不会调用的)

if (dataToCache != null) {

Object data = dataToCache;

dataToCache = null;

cacheData(data);

}

if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {

return true;

}

sourceCacheGenerator = null;

loadData = null;

boolean started = false;

while (!started && hasNextModelLoader()) {

// 关注点4 getLoadData()方法内部会在modelLoaders里面找到ModelLoder对象

// (每个Generator对应一个ModelLoader),

// 并使用modelLoader.buildLoadData方法返回一个loadData列表

loadData = helper.getLoadData().get(loadDataListIndex++);

if (loadData != null

&& (helper.getDiskCacheStrategy().isDataCache able(loadData.fetcher.getDataSource())

|| helper.hasLoadPath(loadData.fetcher.getDat aClass()))) {

started = true;

// 关注点6 通过loadData对象的fetcher对象(有关注点3的分析可知其实现类为HttpUrlFetcher)的

// loadData方法来获取图片数据

loadData.fetcher.loadData(helper.getPriority(), this);

}

}

return started;

}

复制代码

12、DecodeHelper#getLoadData

List<LoadData<?>> getLoadData() {

if (!isLoadDataSet) {

isLoadDataSet = true;

loadData.clear();

List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model) ;

//noinspection ForLoopReplaceableByForEach to improve perf

for (int i = 0, size = modelLoaders.size(); i < size; i++) {

ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);

// 注意:这里最终是通过HttpGlideUrlLoader的buildLoadData获取到实际的loadData对象

LoadData<?> current =

modelLoader.buildLoadData(model, width, height, options);

if (current != null) {

loadData.add(current);

}

}

}

return loadData;

}

复制代码

13、HttpGlideUrlLoader#buildLoadData

@Override

public LoadData buildLoadData(@NonNull GlideUrl model, int width, int height,

@NonNull Options options) {

// GlideUrls memoize parsed URLs so caching them saves a few object instantiations and time

// spent parsing urls.

GlideUrl url = model;

if (modelCache != null) {

url = modelCache.get(model, 0, 0);

if (url == null) {

// 关注点5

modelCache.put(model, 0, 0, model);

url = model;

}

}

int timeout = options.get(TIMEOUT);

// 注意,这里创建了一个DataFetcher的实现类HttpUrlFetcher

return new LoadData<>(url, new HttpUrlFetcher(url, timeout));

}

// 关注点5

public void put(A model, int width, int height, B value) {

ModelKey key = ModelKey.get(model, width, height);

// 最终是通过LruCache来缓存对应的值,key是一个ModelKey对象(由model、width、height三个属性组成)

cache.put(key, value);

}

复制代码

从这里的分析,我们明白了HttpUrlFetcher实际上就是最终的请求执行者,而且,我们知道了Glide会使用LruCache来对解析后的url来进行缓存,以便后续可以省去解析url的时间。

14、HttpUrlFetcher#loadData

@Override

public void loadData(@NonNull Priority priority,

@NonNull DataCallback<? super InputStream> callback) {

long startTime = LogTime.getLogTime();

try {

// 关注点6

// loadDataWithRedirects内部是通过HttpURLConnection网络请求数据

InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());

// 请求成功回调onDataReady()

callback.onDataReady(result);

} catch (IOException e) {

if (Log.isLoggable(TAG, Log.DEBUG)) {

Log.d(TAG, “Failed to load data for url”, e);

}

callback.onLoadFailed(e);

} finally {

if (Log.isLoggable(TAG, Log.VERBOSE)) {

Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));

}

}

}

private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl,

Map<String, String> headers) throws IOException {

urlConnection.connect();

// Set the stream so that it’s closed in cleanup to avoid resource leaks. See #2352.

stream = urlConnection.getInputStream();

if (isCancelled) {

return null;

}

final int statusCode = urlConnection.getResponseCode();

// 只要是2xx形式的状态码则判断为成功

if (isHttpOk(statusCode)) {

// 从urlConnection中获取资源流

return getStreamForSuccessfulRequest(urlConnection);

} else if (isHttpRedirect(statusCode)) {

最后

针对Android程序员,我这边给大家整理了一些资料,包括不限于高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!

  • Android前沿技术大纲

  • 全套体系化高级架构视频

Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、混合式开发(ReactNative+Weex)全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

ty priority,

@NonNull DataCallback<? super InputStream> callback) {

long startTime = LogTime.getLogTime();

try {

// 关注点6

// loadDataWithRedirects内部是通过HttpURLConnection网络请求数据

InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());

// 请求成功回调onDataReady()

callback.onDataReady(result);

} catch (IOException e) {

if (Log.isLoggable(TAG, Log.DEBUG)) {

Log.d(TAG, “Failed to load data for url”, e);

}

callback.onLoadFailed(e);

} finally {

if (Log.isLoggable(TAG, Log.VERBOSE)) {

Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));

}

}

}

private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl,

Map<String, String> headers) throws IOException {

urlConnection.connect();

// Set the stream so that it’s closed in cleanup to avoid resource leaks. See #2352.

stream = urlConnection.getInputStream();

if (isCancelled) {

return null;

}

final int statusCode = urlConnection.getResponseCode();

// 只要是2xx形式的状态码则判断为成功

if (isHttpOk(statusCode)) {

// 从urlConnection中获取资源流

return getStreamForSuccessfulRequest(urlConnection);

} else if (isHttpRedirect(statusCode)) {

最后

针对Android程序员,我这边给大家整理了一些资料,包括不限于高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!

  • Android前沿技术大纲

[外链图片转存中…(img-xHacuK6p-1713706478216)]

  • 全套体系化高级架构视频

[外链图片转存中…(img-mui3bdDR-1713706478217)]

Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、混合式开发(ReactNative+Weex)全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-I8EVmWAq-1713706478217)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/765808
推荐阅读
相关标签
  

闽ICP备14008679号