Glide 图片加载框架源码解析

wshunli
2018-09-17 / 0 评论 / 204 阅读 / 正在检测是否收录...

本文介绍 Glide 图片加载框架,包含简单的使用和源码解析。

Glide 是一个快速高效的 Android 图片加载库,注重于平滑的滚动。Glide 提供了易用的 API,高性能、可扩展的图片解码管道,以及自动的资源池技术。https://muyangmin.github.io/glide-docs-cn/

Glide 支持拉取,解码和展示视频快照,图片,和 GIF 动画。Glide 的 API 是如此的灵活,开发者甚至可以插入和替换成自己喜爱的任何网络栈。默认情况下,Glide 使用的是一个定制化的基于 HttpUrlConnection 的栈,但同时也提供了与 Google Volley 和 Square OkHttp 快速集成的工具库。

一、使用方法

implementation 'com.github.bumptech.glide:glide:4.12.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
Glide.with(this)
    .asBitmap()
    .load("https://cdn.wshunli.com/logo.png")
    .placeholder(R.drawable.loading)
    .error(R.drawable.error)
    .skipMemoryCache(true)
    .diskCacheStrategy(DiskCacheStrategy.NONE)
    .override(100, 100)
    .into(imageView);

https://www.wshunli.com/posts/d82d8606.html

https://muyangmin.github.io/glide-docs-cn/doc/getting-started.html

二、Glide 图片加载流程

2.1、with() 方法

// Glide
public static RequestManager with(@NonNull Context context) {
    return getRetriever(context).get(context);
}
public static RequestManager with(@NonNull Activity activity) {
    return getRetriever(activity).get(activity);
}
public static RequestManager with(@NonNull FragmentActivity activity) {
    return getRetriever(activity).get(activity);
}
public static RequestManager with(@NonNull Fragment fragment) {
    return getRetriever(fragment.getActivity()).get(fragment);
}
@Deprecated
public static RequestManager with(@NonNull android.app.Fragment fragment) {
    return getRetriever(fragment.getActivity()).get(fragment);
}
public static RequestManager with(@NonNull View view) {
    return getRetriever(view.getContext()).get(view);
}
//
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
    // ***
    // (1)构造 Glide 对象,单例模式
    return Glide.get(context).getRequestManagerRetriever();
}
// (1)构造
private static volatile Glide glide;
public static Glide get(@NonNull Context context) {
    if (glide == null) {
        GeneratedAppGlideModule annotationGeneratedModule =
            getAnnotationGeneratedGlideModules(context.getApplicationContext());
        synchronized (Glide.class) {
            if (glide == null) {
                checkAndInitializeGlide(context, annotationGeneratedModule);
            }
        }
    }
    return glide;
}
// 最终 GlideBuilder 构造 glide 对象
private static void initializeGlide(
    @NonNull Context context,
    @NonNull GlideBuilder builder,
    @Nullable GeneratedAppGlideModule annotationGeneratedModule) {
    Glide glide = builder.build(applicationContext);
    Glide.glide = glide;
}
// (2)获取 RequestManagerRetriever
private final RequestManagerRetriever requestManagerRetriever;
public RequestManagerRetriever getRequestManagerRetriever() {
    return requestManagerRetriever;
}

然后调用 RequestManagerRetriever#get() 获取 RequestManager

2.2、load() 方法

// RequestManager
public RequestBuilder<TranscodeType> load(@Nullable String string) {
    return loadGeneric(string);
}
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
    if (isAutoCloneEnabled()) {
        return clone().loadGeneric(model);
    }
    this.model = model;
    isModelSet = true;
    return selfOrThrowIfLocked();
}

将数据存入 RequestManager ,最后返回 RequestBuilder对象

2.3、into() 方法

// RequestBuilder
private final GlideContext glideContext;
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
    Util.assertMainThread();
    Preconditions.checkNotNull(view);
    //***
    // (2) into 方法
    return into(
        // (1) 构造 ViewTarget
        glideContext.buildImageViewTarget(view, transcodeClass),
        // requestOptions
        requestOptions,
        // 运行在主线程的线程池
        Executors.mainThreadExecutor());
}

(1) ImageViewTargetFactory 构造 ViewTarget

// GlideContext
public <X> ViewTarget<ImageView, X> buildImageViewTarget(
    @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
    return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
}
// ImageViewTargetFactory
public class ImageViewTargetFactory {
    @NonNull
    @SuppressWarnings("unchecked")
    public <Z> ViewTarget<ImageView, Z> buildTarget(
        @NonNull ImageView view, @NonNull Class<Z> clazz) {
        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)");
        }
    }
}

(2)RequestBuilder#into 方法

// RequestBuilder
private final RequestManager requestManager;
private <Y extends Target<TranscodeType>> Y into(
    @NonNull Y target,
    @Nullable RequestListener<TranscodeType> targetListener,
    BaseRequestOptions<?> options,
    Executor callbackExecutor) {
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
        throw new IllegalArgumentException("You must call #load() before calling #into()");
    }
    // 构造 SingleRequest 请求对象
    Request request = buildRequest(target, targetListener, options, callbackExecutor);
    Request previous = target.getRequest();
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
        if (!Preconditions.checkNotNull(previous).isRunning()) {
            previous.begin();
        }
        return target;
    }
    requestManager.clear(target);
    target.setRequest(request);
    // 发送请求
    requestManager.track(target, request);
    return target;
}
// RequestManager
private final RequestTracker requestTracker;
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
    targetTracker.track(target);
    requestTracker.runRequest(request);
}
// RequestTracker 真正执行请求
public void runRequest(@NonNull Request request) {
    requests.add(request);
    if (!isPaused) {
        // (3)发送请求
        request.begin();
    } else {
        request.clear();
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "Paused, delaying request");
        }
        pendingRequests.add(request);
    }
}

(3)SingleRequest 发送请求

public void begin() {
    synchronized (requestLock) {
        assertNotCallingCallbacks();
        stateVerifier.throwIfRecycled();
        startTime = LogTime.getLogTime();
        if (model == null) {
            if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
                width = overrideWidth;
                height = overrideHeight;
            }
            int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
            // 记载失败回调
            onLoadFailed(new GlideException("Received null model"), logLevel);
            return;
        }
        // ***
        status = Status.WAITING_FOR_SIZE;
        if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
            // 准备好加载图片
            onSizeReady(overrideWidth, overrideHeight);
        } else {
            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));
        }
    }
}
private volatile Engine engine;
public void onSizeReady(int width, int height) {
    // ***
    //(4)Engine 的 load() 方法
    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.getUseUnlimitedSourceGeneratorsPool(),
        requestOptions.getUseAnimationPool(),
        requestOptions.getOnlyRetrieveFromCache(),
        // SingleRequest 对象
        this,
        callbackExecutor);
    // ***
}

(4)Engine#load 方法

// Engine#load 最终执行 waitForExistingOrStartNewJob 方法
private <R> LoadStatus waitForExistingOrStartNewJob(
    GlideContext glideContext,
    Object model,
    Key signature,
    int width,
    int height,
    Class<?> resourceClass,
    Class<R> transcodeClass,
    Priority priority,
    DiskCacheStrategy diskCacheStrategy,
    Map<Class<?>, Transformation<?>> transformations,
    boolean isTransformationRequired,
    boolean isScaleOnlyOrNoTransform,
    Options options,
    boolean isMemoryCacheable,
    boolean useUnlimitedSourceExecutorPool,
    boolean useAnimationPool,
    boolean onlyRetrieveFromCache,
    // SingleRequest 对象
    ResourceCallback cb,
    Executor callbackExecutor,
    EngineKey key,
    long startTime) {
    // ***
    EngineJob<R> engineJob =
        engineJobFactory.build(
        key,
        isMemoryCacheable,
        useUnlimitedSourceExecutorPool,
        useAnimationPool,
        onlyRetrieveFromCache);
    // ***
    jobs.put(key, engineJob);
    // (5) 最终回调 SingleRequest#onResourceReady 
    engineJob.addCallback(cb, callbackExecutor);
    // ***
    return new LoadStatus(cb, engineJob);
}

(5) SingleRequest#onResourceReady

// SingleRequest
public void onResourceReady(
    Resource<?> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
    stateVerifier.throwIfRecycled();
    Resource<?> toRelease = null;
    try {
        synchronized (requestLock) {
            // ***
            // 获取 GlideBitmapDrawable、GifDrawable 对象
            Object received = resource.get();
            // ***
            onResourceReady(
                (Resource<R>) resource, (R) received, dataSource, isLoadedFromAlternateCacheKey);
        }
    } finally {
        if (toRelease != null) {
            engine.release(toRelease);
        }
    }
}

private final Target<R> target;
private void onResourceReady(
    Resource<R> resource, R result, DataSource dataSource, boolean isAlternateCacheKey) {
    boolean isFirstResource = isFirstReadyResource();
    status = Status.COMPLETE;
    this.resource = resource;
    // ***
    isCallingCallbacks = true;
    try {
        // ***
        // 在 (2)构造 SingleRequest 请求对象时,传入 (1)构造的 ViewTarget
        // BitmapImageViewTarget、DrawableImageViewTarget 类型
        // 最终回调父类 ImageViewTarget#onResourceReady
        target.onResourceReady(result, animation);
        // ***
    } finally {
        isCallingCallbacks = false;
    }

    notifyLoadSuccess();
}

(6)ImageViewTarget#onResourceReady 方法

public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
    if (transition == null || !transition.transition(resource, this)) {
        setResourceInternal(resource);
    } else {
        maybeUpdateAnimatable(resource);
    }
}
private void setResourceInternal(@Nullable Z resource) {
    setResource(resource);
    maybeUpdateAnimatable(resource);
}
// 抽象方法,最终调用子类 setResource 方法
protected abstract void setResource(@Nullable Z resource);

// DrawableImageViewTarget#setResource
protected void setResource(@Nullable Drawable resource) {
    view.setImageDrawable(resource);
}
// BitmapImageViewTarget#setResource
protected void setResource(Bitmap resource) {
    view.setImageBitmap(resource);
}

好复杂啊。

三、缓存机制

Glide.with(this)
    .load("https://cdn.wshunli.com/logo.png")
    // 内存缓存
    .skipMemoryCache(true)
    // 硬盘缓存
    .diskCacheStrategy(DiskCacheStrategy.NONE)
    .into(imageView);

3.1、缓存 Key

// Engine#load()
private final EngineKeyFactory keyFactory;
public <R> LoadStatus load(
    GlideContext glideContext,
    Object model,
    Key signature,
    int width,
    int height,
    Class<?> resourceClass,
    Class<R> 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,
    Executor callbackExecutor) {
    long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;

    // 获取缓存 key
    EngineKey key =
        keyFactory.buildKey(
        model,
        signature,
        width,
        height,
        transformations,
        resourceClass,
        transcodeClass,
        options);

    EngineResource<?> memoryResource;
    synchronized (this) {
        // 3.2内存缓存
        memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
        if (memoryResource == null) {
            // ***
            // waitForExistingOrStartNewJob
        }
    }
    // 加载图片
    cb.onResourceReady(
        memoryResource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false);
    return null;
}

3.2、内存缓存

private EngineResource<?> loadFromMemory(
    EngineKey key, boolean isMemoryCacheable, long startTime) {
    // skipMemoryCache 方法设置
    if (!isMemoryCacheable) {
        return null;
    }
    // (1)从 activeResources 中获取资源,正在使用中
    EngineResource<?> active = loadFromActiveResources(key);
    if (active != null) {
        return active;
    }
    // (2)LruCache 算法获取
    EngineResource<?> cached = loadFromCache(key);
    if (cached != null) {
        return cached;
    }
    return null;
}
// (1)
private final ActiveResources activeResources;
private EngineResource<?> loadFromActiveResources(Key key) {
    EngineResource<?> active = activeResources.get(key);
    if (active != null) {
        active.acquire();
    }
    return active;
}
// (2)
private EngineResource<?> loadFromCache(Key key) {
    EngineResource<?> cached = getEngineResourceFromCache(key);
    if (cached != null) {
        cached.acquire();
        activeResources.activate(key, cached);
    }
    return cached;
}

private EngineResource<?> getEngineResourceFromCache(Key key) {
    Resource<?> cached = cache.remove(key);
    final EngineResource<?> result;
    if (cached == null) {
        result = null;
    } else if (cached instanceof EngineResource) {
        result = (EngineResource<?>) cached;
    } else {
        result =
            new EngineResource<>(
            cached, /*isMemoryCacheable=*/ true, /*isRecyclable=*/ true, key, /*listener=*/ this);
    }
    return result;
}

3.3、硬盘缓存

Glide 的硬盘缓存策略:

DiskCacheStrategy.NONE: 表示不缓存任何内容
DiskCacheStrategy.DATA: 表示只缓存原始图片
DiskCacheStrategy.RESOURCE: 表示只缓存转换过后的图片
DiskCacheStrategy.ALL : 表示既缓存原始图片,也缓存转换过后的图片
DiskCacheStrategy.AUTOMATIC: 表示让 Glide 根据图片资源智能地选择使用哪一种缓存策略

1、Engine#load 方法中,没有内存缓存会调用 waitForExistingOrStartNewJob 方法

// Engine
private <R> LoadStatus waitForExistingOrStartNewJob(
    GlideContext glideContext,
    Object model,
    Key signature,
    int width,
    int height,
    Class<?> resourceClass,
    Class<R> 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,
    Executor callbackExecutor,
    EngineKey key,
    long startTime) {
    // ***
    EngineJob<R> engineJob =
        engineJobFactory.build(
        key,
        isMemoryCacheable,
        useUnlimitedSourceExecutorPool,
        useAnimationPool,
        onlyRetrieveFromCache);

    DecodeJob<R> decodeJob =
        decodeJobFactory.build(
        glideContext,
        model,
        key,
        signature,
        width,
        height,
        resourceClass,
        transcodeClass,
        priority,
        diskCacheStrategy,
        transformations,
        isTransformationRequired,
        isScaleOnlyOrNoTransform,
        onlyRetrieveFromCache,
        options,
        engineJob);

    jobs.put(key, engineJob);

    engineJob.addCallback(cb, callbackExecutor);
    // 开始解码
    engineJob.start(decodeJob);
    // ***
    return new LoadStatus(cb, engineJob);
}
// EngineJob#start
public synchronized void start(DecodeJob<R> decodeJob) {
    this.decodeJob = decodeJob;
    // 在线程池中执行 decodeJob
    GlideExecutor executor =
        decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
    executor.execute(decodeJob);
}

2、DecodeJob#run 方法

// DecodeJob
public void run() {
    // ***
    runWrapped();
    // ***
}
private void runWrapped() {
    switch (runReason) {
        case INITIALIZE:
            stage = getNextStage(Stage.INITIALIZE);
            currentGenerator = getNextGenerator();
            runGenerators();
            break;
        case SWITCH_TO_SOURCE_SERVICE:
            runGenerators();
            break;
        case DECODE_DATA:
            decodeFromRetrievedData();
            break;
        default:
            throw new IllegalStateException("Unrecognized run reason: " + runReason);
    }
}

参考资料
1、Glide源码分析 | lightSky'Blog
http://www.lightskystreet.com/2015/10/12/glide_source_analysis/
2、Android Glide源码解析 - 简书
https://www.jianshu.com/p/0c383eaa5675
3、Android Glide源码解析 | Frodo's Blog
http://frodoking.github.io/2015/10/10/android-glide/
4、Android源码分析:手把手带你分析 Glide的缓存功能 - CSDN博客
https://blog.csdn.net/carson_ho/article/details/79256892

0

评论 (0)

取消