0
点赞
收藏
分享

微信扫一扫

Glide框架解析,androidstudio开发实战

八怪不姓丑 2022-03-17 阅读 55

}

// 其实loadGeneric()方法也没几行代码,这里分别调用了Glide.buildStreamModelLoader()方法和Glide.buildFileDescriptorModelLoader()方法来获得ModelLoader对象。
// ModelLoader对象是用于加载图片的,而我们给load()方法传入不同类型的参数,这里也会得到不同的ModelLoader对象。
// 由于我们刚才传入的参数是String.class,因此最终得到的是StreamStringLoader对象,它是实现了ModelLoader接口的。
private DrawableTypeRequest loadGeneric(Class modelClass) {
ModelLoader<T, InputStream> streamModelLoader = Glide.buildStreamModelLoader(modelClass, context);
ModelLoader<T, ParcelFileDescriptor> fileDescriptorModelLoader =
Glide.buildFileDescriptorModelLoader(modelClass, context);
if (modelClass != null && streamModelLoader == null && fileDescriptorModelLoader == null) {
throw new IllegalArgumentException("Unknown type " + modelClass + “. You must provide a Model of a type for”

  • " which there is a registered ModelLoader, if you are using a custom model, you must first call"
  • " Glide#register with a ModelLoaderFactory for your custom model class");
    }
    // loadGeneric()方法是要返回一个DrawableTypeRequest对象的,
    // 因此在loadGeneric()方法的最后又去new了一个DrawableTypeRequest对象,
    // 然后把刚才获得的ModelLoader对象,还有一大堆杂七杂八的东西都传了进去。具体每个参数的含义和作用就不解释了,我们只看主线流程。
    return optionsApplier.apply(
    new DrawableTypeRequest(modelClass, streamModelLoader, fileDescriptorModelLoader, context,
    glide, requestTracker, lifecycle, optionsApplier));
    }
    }

那么这个DrawableTypeRequest的作用是什么呢?我们来看下它的源码,如下所示:

public class DrawableTypeRequest extends DrawableRequestBuilder implements DownloadOptions {
private final ModelLoader<ModelType, InputStream> streamModelLoader;
private final ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader;
private final RequestManager.OptionsApplier optionsApplier;

private static <A, Z, R> FixedLoadProvider<A, ImageVideoWrapper, Z, R> buildProvider(Glide glide,
ModelLoader<A, InputStream> streamModelLoader,
ModelLoader<A, ParcelFileDescriptor> fileDescriptorModelLoader, Class resourceClass,
Class transcodedClass,
ResourceTranscoder<Z, R> transcoder) {
if (streamModelLoader == null && fileDescriptorModelLoader == null) {
return null;
}

if (transcoder == null) {
transcoder = glide.buildTranscoder(resourceClass, transcodedClass);
}
DataLoadProvider<ImageVideoWrapper, Z> dataLoadProvider = glide.buildDataProvider(ImageVideoWrapper.class,
resourceClass);
ImageVideoModelLoader modelLoader = new ImageVideoModelLoader(streamModelLoader,
fileDescriptorModelLoader);
return new FixedLoadProvider<A, ImageVideoWrapper, Z, R>(modelLoader, transcoder, dataLoadProvider);
}

DrawableTypeRequest(Class modelClass, ModelLoader<ModelType, InputStream> streamModelLoader,
ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader, Context context, Glide glide,
RequestTracker requestTracker, Lifecycle lifecycle, RequestManager.OptionsApplier optionsApplier) {
super(context, modelClass,
buildProvider(glide, streamModelLoader, fileDescriptorModelLoader, GifBitmapWrapper.class,
GlideDrawable.class, null),
glide, requestTracker, lifecycle);
this.streamModelLoader = streamModelLoader;
this.fileDescriptorModelLoader = fileDescriptorModelLoader;
this.optionsApplier = optionsApplier;
}

/**

  • 最主要的就是它提供了asBitmap()和asGif()这两个方法。这两个方法我们在上一篇文章当中都是学过的,分别是用于强制指定加载静态图片和动态图片。而从源码中可以看出,它们分别又创建了一个BitmapTypeRequest和GifTypeRequest,如果没有进行强制指定的话,那默认就是使用DrawableTypeRequest。
    */
    public BitmapTypeRequest asBitmap() {
    return optionsApplier.apply(new BitmapTypeRequest(this, streamModelLoader,
    fileDescriptorModelLoader, optionsApplier));
    }

/**
*
*/
public GifTypeRequest asGif() {
return optionsApplier.apply(new GifTypeRequest(this, streamModelLoader, optionsApplier));
}


}

这个类中的代码本身就不多,我只是稍微做了一点简化。可以看到,最主要的就是它提供了asBitmap()和asGif()这两个方法。这两个方法我们在上一篇文章当中都是学过的,分别是用于强制指定加载静态图片和动态图片。而从源码中可以看出,它们分别又创建了一个BitmapTypeRequest和GifTypeRequest,如果没有进行强制指定的话,那默认就是使用DrawableTypeRequest。

好的,那么我们再回到RequestManager的load()方法中。刚才已经分析过了,fromString()方法会返回一个DrawableTypeRequest对象,接下来会调用这个对象的load()方法,把图片的URL地址传进去。但是我们刚才看到了,DrawableTypeRequest中并没有load()方法,那么很容易就能猜想到,load()方法是在父类当中的。

DrawableTypeRequest的父类是DrawableRequestBuilder,我们来看下这个类的源码:

public class DrawableRequestBuilder
extends GenericRequestBuilder<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable>
implements BitmapOptions, DrawableOptions {

DrawableRequestBuilder(Context context, Class modelClass,
LoadProvider<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable> loadProvider, Glide glide,
RequestTracker requestTracker, Lifecycle lifecycle) {
super(context, modelClass, loadProvider, GlideDrawable.class, glide, requestTracker, lifecycle);
// Default to animating.
crossFade();
}

public DrawableRequestBuilder thumbnail(
DrawableRequestBuilder<?> thumbnailRequest) {
super.thumbnail(thumbnailRequest);
return this;
}

@Override
public DrawableRequestBuilder thumbnail(
GenericRequestBuilder<?, ?, ?, GlideDrawable> thumbnailRequest) {
super.thumbnail(thumbnailRequest);
return this;
}

@Override
public DrawableRequestBuilder thumbnail(float sizeMultiplier) {
super.thumbnail(sizeMultiplier);
return this;
}

@Override
public DrawableRequestBuilder sizeMultiplier(float sizeMultiplier) {
super.sizeMultiplier(sizeMultiplier);
return this;
}

@Override
public DrawableRequestBuilder decoder(ResourceDecoder<ImageVideoWrapper, GifBitmapWrapper> decoder) {
super.decoder(decoder);
return this;
}

@Override
public DrawableRequestBuilder cacheDecoder(ResourceDecoder<File, GifBitmapWrapper> cacheDecoder) {
super.cacheDecoder(cacheDecoder);
return this;
}

@Override
public DrawableRequestBuilder encoder(ResourceEncoder encoder) {
super.encoder(encoder);
return this;
}

@Override
public DrawableRequestBuilder priority(Priority priority) {
super.priority(priority);
return this;
}

public DrawableRequestBuilder transform(BitmapTransformation… transformations) {
return bitmapTransform(transformations);
}

public DrawableRequestBuilder centerCrop() {
return transform(glide.getDrawableCenterCrop());
}

public DrawableRequestBuilder fitCenter() {
return transform(glide.getDrawableFitCenter());
}

public DrawableRequestBuilder bitmapTransform(Transformation… bitmapTransformations) {
GifBitmapWrapperTransformation[] transformations =
new GifBitmapWrapperTransformation[bitmapTransformations.length];
for (int i = 0; i < bitmapTransformations.length; i++) {
transformations[i] = new GifBitmapWrapperTransformation(glide.getBitmapPool(), bitmapTransformations[i]);
}
return transform(transformations);
}

@Override
public DrawableRequestBuilder transform(Transformation… transformation) {
super.transform(transformation);
return this;
}

@Override
public DrawableRequestBuilder transcoder(
ResourceTranscoder<GifBitmapWrapper, GlideDrawable> transcoder) {
super.transcoder(transcoder);
return this;
}

public final DrawableRequestBuilder crossFade() {
super.animate(new DrawableCrossFadeFactory());
return this;
}

public DrawableRequestBuilder crossFade(int duration) {
super.animate(new DrawableCrossFadeFactory(duration));
return this;
}

public DrawableRequestBuilder crossFade(int animationId, int duration) {
super.animate(new DrawableCrossFadeFactory(context, animationId,
duration));
return this;
}

@Override
public DrawableRequestBuilder dontAnimate() {
super.dontAnimate();
return this;
}

@Override
public DrawableRequestBuilder animate(ViewPropertyAnimation.Animator animator) {
super.animate(animator);
return this;
}

@Override
public DrawableRequestBuilder animate(int animationId) {
super.animate(animationId);
return this;
}

@Override
public DrawableRequestBuilder placeholder(int resourceId) {
super.placeholder(resourceId);
return this;
}

@Override
public DrawableRequestBuilder placeholder(Drawable drawable) {
super.placeholder(drawable);
return this;
}

@Override
public DrawableRequestBuilder fallback(Drawable drawable) {
super.fallback(drawable);
return this;
}

@Override
public DrawableRequestBuilder fallback(int resourceId) {
super.fallback(resourceId);
return this;
}

@Override
public DrawableRequestBuilder error(int resourceId) {
super.error(resourceId);
return this;
}

@Override
public DrawableRequestBuilder error(Drawable drawable) {
super.error(drawable);
return this;
}

@Override
public DrawableRequestBuilder listener(
RequestListener<? super ModelType, GlideDrawable> requestListener) {
super.listener(requestListener);
return this;
}
@Override
public DrawableRequestBuilder diskCacheStrategy(DiskCacheStrategy strategy) {
super.diskCacheStrategy(strategy);
return this;
}

@Override
public DrawableRequestBuilder skipMemoryCache(boolean skip) {
super.skipMemoryCache(skip);
return this;
}

@Override
public DrawableRequestBuilder override(int width, int height) {
super.override(width, height);
return this;
}

@Override
public DrawableRequestBuilder sourceEncoder(Encoder sourceEncoder) {
super.sourceEncoder(sourceEncoder);
return this;
}

@Override
public DrawableRequestBuilder dontTransform() {
super.dontTransform();
return this;
}

@Override
public DrawableRequestBuilder signature(Key signature) {
super.signature(signature);
return this;
}

@Override
public DrawableRequestBuilder load(ModelType model) {
super.load(model);
return this;
}

@Override
public DrawableRequestBuilder clone() {
return (DrawableRequestBuilder) super.clone();
}

@Override
public Target into(ImageView view) {
return super.into(view);
}

@Override
void applyFitCenter() {
fitCenter();
}

@Override
void applyCenterCrop() {
centerCrop();
}
}

DrawableRequestBuilder中有很多个方法,这些方法其实就是Glide绝大多数的API了。里面有不少我们在上篇文章中已经用过了,比如说placeholder()方法、error()方法、diskCacheStrategy()方法、override()方法等。当然还有很多暂时还没用到的API,我们会在后面的文章当中学习。

到这里,第二步load()方法也就分析结束了。为什么呢?因为你会发现DrawableRequestBuilder类中有一个into()方法(上述代码第220行),也就是说,最终load()方法返回的其实就是一个DrawableTypeRequest对象。那么接下来我们就要进行第三步了,分析into()方法中的逻辑。

2.3、总结

load方法最终做的就是进行一些初始化的操作,获得了一个DrawableTypeRequest对象,通过这个对象我们就可以获得图片请求的request,然后再接下来的into方法中使用。

3、into()

3.1、详解

如果说前面两步都是在准备开胃小菜的话,那么现在终于要进入主菜了,因为into()方法也是整个Glide图片加载流程中逻辑最复杂的地方。

不过从刚才的代码来看,into()方法中并没有任何逻辑,只有一句super.into(view)。那么很显然,into()方法的具体逻辑都是在DrawableRequestBuilder的父类当中了。

3.1、源码

DrawableRequestBuilder的父类是GenericRequestBuilder,我们来看一下GenericRequestBuilder类中的into()方法,如下所示:

public Target into(ImageView view) {
Util.assertMainThread();
if (view == null) {
throw new IllegalArgumentException(“You must pass in a non null View”);
}
if (!isTransformationSet && view.getScaleType() != null) {
switch (view.getScaleType()) {
case CENTER_CROP:
applyCenterCrop();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
applyFitCenter();
break;
// C A S E S − O M I T T E D CASES-OMITTED CASESOMITTED
default:
// Do nothing.
}
}
return into(glide.buildImageViewTarget(view, transcodeClass));
}

这里前面一大堆的判断逻辑我们都可以先不用管,等到后面文章讲transform的时候会再进行解释,现在我们只需要关注最后一行代码。最后一行代码先是调用了glide.buildImageViewTarget()方法,这个方法会构建出一个Target对象,Target对象则是用来最终展示图片用的,如果我们跟进去的话会看到如下代码:

Target buildImageViewTarget(ImageView imageView, Class transcodedClass) {
return imageViewTargetFactory.buildTarget(imageView, transcodedClass);
}

这里其实又是调用了ImageViewTargetFactory的buildTarget()方法,我们继续跟进去,代码如下所示:

public class ImageViewTargetFactory {

@SuppressWarnings(“unchecked”)
public Target buildTarget(ImageView view, Class clazz) {
if (GlideDrawable.class.isAssignableFrom(clazz)) {
return (Target) new GlideDrawableImageViewTarget(view);
} else if (Bitmap.class.equals(clazz)) {
return (Target) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (Target) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException("Unhandled class: " + clazz

  • “, try .as*(Class).transcode(ResourceTranscoder)”);
    }
    }
    }

可以看到,在buildTarget()方法中会根据传入的class参数来构建不同的Target对象。那如果你要分析这个class参数是从哪儿传过来的,这可有得你分析了,简单起见我直接帮大家梳理清楚。这个class参数其实基本上只有两种情况,如果你在使用Glide加载图片的时候调用了asBitmap()方法,那么这里就会构建出BitmapImageViewTarget对象,否则的话构建的都是GlideDrawableImageViewTarget对象。至于上述代码中的DrawableImageViewTarget对象,这个通常都是用不到的,我们可以暂时不用管它。

也就是说,通过glide.buildImageViewTarget()方法,我们构建出了一个GlideDrawableImageViewTarget对象。那现在回到刚才into()方法的最后一行,可以看到,这里又将这个参数传入到了GenericRequestBuilder另一个接收Target对象的into()方法当中了。我们来看一下这个into()方法的源码:

public <Y extends Target> Y into(Y target) {
Util.assertMainThread();
if (target == null) {
throw new IllegalArgumentException(“You must pass in a non null Target”);
}
if (!isModelSet) {
throw new IllegalArgumentException(“You must first set a model (try #load())”);
}
Request previous = target.getRequest();
if (previous != null) {
previous.clear();
requestTracker.removeRequest(previous);
previous.recycle();
}
Request request = buildRequest(target);
target.setRequest(request);
lifecycle.addListener(target);
// 重点:Request是用来发出加载图片请求的,它是Glide中非常关键的一个组件。
requestTracker.runRequest(request);
return target;
}

这里我们还是只抓核心代码,其实只有两行是最关键的,第15行调用buildRequest()方法构建出了一个Request对象,还有第18行来执行这个Request。

Request是用来发出加载图片请求的,它是Glide中非常关键的一个组件。我们先来看buildRequest()方法是如何构建Request对象的:

private Request buildRequest(Target target) {
if (priority == null) {
priority = Priority.NORMAL;
}
return buildRequestRecursive(target, null);
}

// buildRequest()方法的内部其实又调用了buildRequestRecursive()方法
private Request buildRequestRecursive(Target target, ThumbnailRequestCoordinator parentCoordinator) {
if (thumbnailRequestBuilder != null) {
if (isThumbnailBuilt) {
throw new IllegalStateException("You cannot use a request as both the main request and a thumbnail, "

  • “consider using clone() on the request(s) passed to thumbnail()”);
    }
    // Recursive case: contains a potentially recursive thumbnail request builder.
    if (thumbnailRequestBuilder.animationFactory.equals(NoAnimation.getFactory())) {
    thumbnailRequestBuilder.animationFactory = animationFactory;
    }

if (thumbnailRequestBuilder.priority == null) {
thumbnailRequestBuilder.priority = getThumbnailPriority();
}

if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !Util.isValidDimensions(thumbnailRequestBuilder.overrideWidth,
thumbnailRequestBuilder.overrideHeight)) {
thumbnailRequestBuilder.override(overrideWidth, overrideHeight);
}

ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest = obtainRequest(target, sizeMultiplier, priority, coordinator);
// Guard against infinite recursion.
isThumbnailBuilt = true;
// Recursively generat

e thumbnail requests.
Request thumbRequest = thumbnailRequestBuilder.buildRequestRecursive(target, coordinator);
isThumbnailBuilt = false;
coordinator.setRequests(fullRequest, thumbRequest);
return coordinator;
} else if (thumbSizeMultiplier != null) {
// Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest = obtainRequest(target, sizeMultiplier, priority, coordinator);
Request thumbnailRequest = obtainRequest(target, thumbSizeMultiplier, getThumbnailPriority(), coordinator);
coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
} else {
// Base case: no thumbnail.’’
// 这里调用了obtainRequest()方法来获取一个Request对象,而obtainRequest()方法中又去调用了GenericRequest的obtain()方法。
return obtainRequest(target, sizeMultiplier, priority, parentCoordinator);
}
}

private Request obtainRequest(Target target, float sizeMultiplier, Priority priority,
RequestCoordinator requestCoordinator) {
return GenericRequest.obtain(
loadProvider,
model,
signature,
context,
priority,
target,
sizeMultiplier,
placeholderDrawable,
placeholderId,
errorPlaceholder,
errorId,
fallbackDrawable,
fallbackResource,
requestListener,
requestCoordinator,
glide.getEngine(),
transformation,
transcodeClass,
isCacheable,
animationFactory,
overrideWidth,
overrideHeight,
diskCacheStrategy);
}

可以看到,buildRequest()方法的内部其实又调用了buildRequestRecursive()方法,而buildRequestRecursive()方法中的代码虽然有点长,但是其中90%的代码都是在处理缩略图的。如果我们只追主线流程的话,那么只需要看第47行代码就可以了。这里调用了obtainRequest()方法来获取一个Request对象,而obtainRequest()方法中又去调用了GenericRequestobtain()方法。注意这个obtain()方法需要传入非常多的参数,而其中很多的参数我们都是比较熟悉的,像什么placeholderId、errorPlaceholder、diskCacheStrategy等等。因此,我们就有理由猜测,刚才在load()方法中调用的所有API,其实都是在这里组装到Request对象当中的。那么我们进入到这个GenericRequest的obtain()方法瞧一瞧:

public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallback,
ResourceCallback {

public static <A, T, Z, R> GenericRequest<A, T, Z, R> obtain(
LoadProvider<A, T, Z, R> loadProvider,
A model,
Key signature,
Context context,
Priority priority,
Target target,
float sizeMultiplier,
Drawable placeholderDrawable,
int placeholderResourceId,
Drawable errorDrawable,
int errorResourceId,
Drawable fallbackDrawable,
int fallbackResourceId,
RequestListener<? super A, R> requestListener,
RequestCoordinator requestCoordinator,
Engine engine,
Transformation transformation,
Class transcodeClass,
boolean isMemoryCacheable,
GlideAnimationFactory animationFactory,
int overrideWidth,
int overrideHeight,
DiskCacheStrategy diskCacheStrategy) {
@SuppressWarnings(“unchecked”)
GenericRequest<A, T, Z, R> request = (GenericRequest<A, T, Z, R>) REQUEST_POOL.poll();
if (request == null) {
// 33行:
request = new GenericRequest<A, T, Z, R>();
}
request.init(loadProvider,
model,
signature,
context,
priority,
target,
sizeMultiplier,
placeholderDrawable,
placeholderResourceId,
errorDrawable,
errorResourceId,
fallbackDrawable,
fallbackResourceId,
requestListener,
requestCoordinator,
engine,
transformation,
transcodeClass,
isMemoryCacheable,
animationFactory,
overrideWidth,
overrideHeight,
diskCacheStrategy);
return request;
}
}

可以看到,这里在第33行去new了一个GenericRequest对象,并在最后一行返回,也就是说,obtain()方法实际上获得的就是一个GenericRequest对象。另外这里又在第35行调用了GenericRequest的init(),里面主要就是一些赋值的代码,将传入的这些参数赋值到GenericRequest的成员变量当中,我们就不再跟进去看了。

好,那现在解决了构建Request对象的问题,接下来我们看一下这个Request对象又是怎么执行的。回到刚才的into()方法,你会发现在第18行调用了requestTracker.runRequest()方法来去执行这个Request,那么我们跟进去瞧一瞧,如下所示:

/**

  • Starts tracking the given request.
    */
    public void runRequest(Request request) {
    requests.add(request);
    if (!isPaused) {
    request.begin();
    } else {
    pendingRequests.add(request);
    }
    }

这里有一个简单的逻辑判断,就是先判断Glide当前是不是处理暂停状态,如果不是暂停状态就调用Request的begin()方法来执行Request,否则的话就先将Request添加到待执行队列里面,等暂停状态解除了之后再执行。

暂停请求的功能仍然不是这篇文章所关心的,这里就直接忽略了,我们重点来看这个begin()方法。由于当前的Request对象是一个GenericRequest,因此这里就需要看GenericRequest中的begin()方法了,如下所示:

@Override
public void begin() {
startTime = LogTime.getLogTime();
if (model == null) {
onException(null);
return;
}
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this);
}
if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable());
}
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished run method in " + LogTime.getElapsedMillis(startTime));
}
}

这里我们来注意几个细节,首先如果model等于null,model也就是我们在第二步load()方法中传入的图片URL地址,这个时候会调用onException()方法。如果你跟到onException()方法里面去看看,你会发现它最终会调用到一个setErrorPlaceholder()当中,如下所示:

private void setErrorPlaceholder(Exception e) {
if (!canNotifyStatusChanged()) {
return;
}
Drawable error = model == null ? getFallbackDrawable() : null;
if (error == null) {
error = getErrorDrawable();
}
if (error == null) {
error = getPlaceholderDrawable();
}
target.onLoadFailed(e, error);
}

这个方法中会先去获取一个error的占位图,如果获取不到的话会再去获取一个loading占位图,然后调用target.onLoadFailed()方法并将占位图传入。那么onLoadFailed()方法中做了什么呢?我们看一下:

public abstract class ImageViewTarget extends ViewTarget<ImageView, Z> implements GlideAnimation.ViewAdapter {

@Override
public void onLoadStarted(Drawable placeholder) {
view.setImageDrawable(placeholder);
}

@Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
view.setImageDrawable(errorDrawable);
}
}

很简单,其实就是将这张error占位图显示到ImageView上而已,因为现在出现了异常,没办法展示正常的图片了。而如果你仔细看下刚才begin()方法的第15行,你会发现它又调用了一个target.onLoadStarted()方法,并传入了一个loading占位图,在也就说,在图片请求开始之前,会先使用这张占位图代替最终的图片显示。这也是我们在上一篇文章中学过的placeholder()和error()这两个占位图API底层的实现原理。

好,那么我们继续回到begin()方法。刚才讲了占位图的实现,那么具体的图片加载又是从哪里开始的呢?是在begin()方法的第10行和第12行。这里要分两种情况,一种是你使用了override() API为图片指定了一个固定的宽高,一种是没有指定。如果指定了的话,就会执行第10行代码,调用onSizeReady()方法。如果没指定的话,就会执行第12行代码,调用target.getSize()方法。这个target.getSize()方法的内部会根据ImageView的layout_width和layout_height值做一系列的计算,来算出图片应该的宽高。具体的计算细节我就不带着大家分析了,总之在计算完之后,它也会调用onSizeReady()方法。也就是说,不管是哪种情况,最终都会调用到onSizeReady()方法,在这里进行下一步操作。那么我们跟到这个方法里面来:

@Override
public void onSizeReady(int width, int height) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
if (status != Status.WAITING_FOR_SIZE) {
return;
}
status = Status.RUNNING;
width = Math.round(sizeMultiplier * width);
height = Math.round(sizeMultiplier * height);
//
ModelLoader<A, T> modelLoader = loadProvider.getModelLoader();
final DataFetcher dataFetcher = modelLoader.getResourceFetcher(model, width, height);
if (dataFetcher == null) {
onException(new Exception(“Failed to load model: '” + model + “’”));
return;
}
ResourceTranscoder<Z, R> transcoder = loadProvider.getTranscoder();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
}

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2020-2021面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节

还有 高级架构技术进阶脑图、Android开发面试专题资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

一线互联网面试专题

379页的Android进阶知识大全

379页的Android进阶知识大全

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
led to load model: ‘" + model + "’"));
return;
}
ResourceTranscoder<Z, R> transcoder = loadProvider.getTranscoder();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
}

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2020-2021面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节

还有 高级架构技术进阶脑图、Android开发面试专题资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

[外链图片转存中…(img-EkpfoR7m-1647529541779)]

[外链图片转存中…(img-efjzkM9d-1647529541780)]

[外链图片转存中…(img-fq1a5EgK-1647529541780)]

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

举报

相关推荐

0 条评论