Glide原理

Glide是google推荐的图片加载框架

使用简单:

Glide.with(this).load(url).into(imageView);

加载流程总结如下:

1)首先,Glide.with(activity)方法得到RequestManager类,这个类的主要作用是将glide 与 整个组件的生命周期绑定在一起。(它实现了LifecycleListener接口,这是一个与Context的生命周期绑定的接口,将request与生命周期绑定,这样就可以通过context的生命周期去操作网络请求的开始,暂停等。)

如何绑定的??答:在Activity上创建一个透明无界面的RequestManagerFragment加入到FragmentManger中,通过添加的Fragment来感知Activity、Fragment的生命周期。因为添加到Activity中的Fragment会跟随Activity的生命周期。

2)通过load方法来初始化一些参数,这里传入的参数给后面的加载方式提供了依据;

3)通过into这个核心方法将图片获取 并 通过一系列处理后加载到相应的控件上,这部分逻辑最为复杂,建立请求,然后通过Engine引擎类将请求进行统一的处理,里面开启了两个线程池-----------磁盘缓存线程池(diskcacheService)和 源线程池(sourceService),并且进行了两层缓存,除了我们常见的内存缓存外,还进行了活动资源的缓存,其中内部的网络请求是通过android原生的HttpUrlConnection完成的。

 

下面主要看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;
            //$CASES-OMITTED$
            default:
                // Do nothing.
        }
    }
    return into(glide.buildImageViewTarget(view, transcodeClass));//重点
}

最终里面调用的是

public > 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);
    requestTracker.runRequest(request);

    return target;
}

其实target就是对View的封装,直接把target当作是View即可。这里的逻辑主要就是对之前请求的彻底清除 和 对新请求的建立 与 绑定生命周期,这也是控件复用时图片不会错位的原因。

 

新建请求调用buildRequest方法

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

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 generate 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.
        return obtainRequest(target, sizeMultiplier, priority, parentCoordinator);
    }
}

请求网络是调用obtainRequest方法。

 

回到into方法中,当新建好请求后,会runRequest。

public void runRequest(Request request) {
    requests.add(request);
    if (!isPaused) {
        request.begin();
    } else {
        pendingRequests.add(request);
    }
}

其中调用了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));
    }
}

可以看到,会计算开始时间,然后将图片加载状态置为等待,然后会对图片大小的合法性进行判断,最后会判断图片的加载状态,如果没有加载完成而且没有加载失败,那么就开始加载图片;

bengin()方法中调用了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 modelLoader = loadProvider.getModelLoader();
    final DataFetcher dataFetcher = modelLoader.getResourceFetcher(model, width, height);

    if (dataFetcher == null) {
        onException(new Exception("Failed to load model: \'" + model + "\'"));
        return;
    }
    ResourceTranscoder transcoder = loadProvider.getTranscoder();
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
        logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
    }
    loadedFromMemoryCache = true;
    //重点
    loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
            priority, isMemoryCacheable, diskCacheStrategy, this);

    loadedFromMemoryCache = resource != null;
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
        logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
    }
}

这里,我们接触了glide最核心的类:Engine类

/**
 * Responsible for starting loads and managing active and cached resources.
 */

从注释可以看出,Engine就是负责开始加载图片 和 管理 活动或缓存 中的资源的引擎类。

Engine主要参数:

***内存缓存  memoryCache

***本地缓存  diskCacheFactory-----------------默认大小 int DEFAULT_DISK_CACHE_SIZE = 250 * 1024 * 1024; 也就是250M。

***处理源资源的线程池   sourceService

***处理本地缓存的线程池  diskCacheService

所以,加载图片会先从缓存中加载,如果找到就将其加入到活动资源中 并 从缓存中删除,如果没找到再从活动资源(activeResource)中找。找到了就使用,找不到再从磁盘缓存中找。

其中activeResource是一个以弱引用为值的map,它是用于存储使用中的资源,之所以在内存缓存的基础上多加了这一层缓存,是为了当内存不足而清除cache中的资源时,不会影响使用中的资源。

你可能感兴趣的:(Android)