(源码分析)Glide(图片异步加载缓存库)发起request获取resource

工作流程:

既然Glide的功能这么强大,那么就一定要学习下源码,看看内部是怎样工作的。

Glide.with((Fragment) t).load(url).into(imageView);

为了好理解,将上面一行代码进行分解:

RequestManager requestManager = Glide.with((Fragment) t);

DrawableTypeRequest drawableTypeRequest = requestManager.load(url);

//class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<ModelType> 

Target<GlideDrawable> target = DrawableRequestBuilder.into(imageView);

这几个类,我们一起了解下。

Glide:单例,提供使用(BitmapRequestBuilder)构建请求、包含engine,BitmapPool,DiskCache,MemoryCache的简单的静态方法。
Engine:启动下载和管理当前正在使用或者缓存的资源。
BitmapPool:接口类型,允许用户重用bitmap 对象。实现类 LruBitmapPool :复用bitmap,使用最近最少使用策略保证池子的大小。
RequestManager:用于管理和启动Glide请求的类,可以使用activity,fragment连接其生命周期方法来智能的中止、启动和重新发起请求。通过实例化一个新对象,或者利用Activity和Fragment的生命周期处理,在Fragment或者Activity中,使用Glide的静态load方法。

DrawableTypeRequest : 创建一个下载请求来下载drawable或者Bitmap drawable。

Target:接口类型,将加载的资源填充到target对象身上。实现类 ImageViewTarget ViewTarget GlideDrawableImageViewTarget等等。

那就从Glide的with()方法开始看。with方法可以接收context、activity、fragment类型。

    /**
     * Begin a load with Glide by passing in a context.
     * 通过传递一个上下文对象来开始Glide。
     * 传入的如果是fragment/Activity,那么这个请求的生命周期就跟fragment/Activity生命周期一样
     * 如果是上下文是application,那么请求的声明周期就是应用级别的。
     * @see #with(android.app.Activity)
     * @see #with(android.app.Fragment)
     * @see #with(android.support.v4.app.Fragment)
     * @see #with(android.support.v4.app.FragmentActivity)
     *
     * @param context Any context, will not be retained.
     * @return A RequestManager for the top level application that can be used to start a load.
     */
    public static RequestManager with(Context context) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(context);
    }
   
   @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public static RequestManager with(Activity activity) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(activity);
    }
    public static RequestManager with(Fragment fragment) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(fragment);
    }

如果传入的是Activity或者Fragment,那么是怎么保证生命周期的?点进去看一下

public RequestManager get(Context context) {
    if (context == null) {
        throw new IllegalArgumentException("You cannot start a load on a null Context");
    } else if (Util.isOnMainThread() && !(context instanceof Application)) {
        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());
        }
    }

    return getApplicationManager(context);
}

 

先判断如果不是在主线程,或者是application类型那么直接return getApplicationManager(context); 以activity类型为例,那么会调到下面的方法。

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public RequestManager get(Activity activity) {
    if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
        return get(activity.getApplicationContext());
    } else {
        assertNotDestroyed(activity);
        android.app.FragmentManager fm = activity.getFragmentManager();
        return fragmentGet(activity, fm);
    }
}

 如果是后台线程的话,继续创建 application级别的 requestmanager则会执行到fragmentGet(activity, fm);

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
        RequestManagerFragment current = getRequestManagerFragment(fm);
        RequestManager requestManager = current.getRequestManager();
        if (requestManager == null) {
            requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
            current.setRequestManager(requestManager);
        }
        return requestManager;
    }

方法内部会创建一个RequestManagerFragment对象 current,是一个fragment对象。     

requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());

将fragment的ActivityFragmentLifecycle 给requestManager。这样在RequestManager内部,通过 添加一个

 addListener(LifecycleListener listener)

就可以保持与fragment的生命周期保持同步。

/**
 * 接口监听Fragment和Activity的生命周期事件。
 */
public interface LifecycleListener {

    /**
     *当Activity或者fragment的onStart方法执行的时候调用。
     */
    void onStart();

    /**
     * 当Activity或者fragment的onStop方法执行的时候调用。
     */
    void onStop();

    /**
     *当Activity或者fragment的onDestroy方法执行的时候调用。
     */
    void onDestroy();
}

在RequestManagManager中

    /**
     *重新开始失败或者暂停的requests.
     */
    @Override
    public void onStart() {
        resumeRequests();
    }

    /**
     * 停止request
     */
    @Override
    public void onStop() {
        pauseRequests();
    }

    /**
     *取消请求,清楚回收资源
     */
    @Override
    public void onDestroy() {
        requestTracker.clearRequests();
    }

以上过程保证了Glide发起的request,与Activity/Fragment的生命周期保持一致,当Activity/Fragment销毁时,取消请求,这样能及时回收资源。

接下来再看下load方法。

  /**
     * 返回一个来下载drawable或者Bitmap drawable的request对象。
     *
     * @see #fromString()
     * @see #load(Object)
     *
     * @param string A file path, or a uri or url handled by {@link com.bumptech.glide.load.model.UriLoader}.
     */
    public DrawableTypeRequest<String> load(String string) {
        return (DrawableTypeRequest<String>) fromString().load(string);
    }

在我们介绍Glide 的功能时,设置的占位图,加载失败展示图,动画效果等都是由DrawableRequestBuilder来完成的。并且包含了具体的发起请求步骤。

	Glide.with((Activity) t).load(url).placeholder(holderId).error(errorId).dontAnimate().dontTransform().into(imageView);

继承自GenericRequestBuilder,它是一个泛型类,可以处理设置选项和初始加载。可以看下它的成员变量

public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> implements Cloneable {
    protected final Class<ModelType> modelClass;
    protected final Context context;
    protected final Glide glide;
    protected final Class<TranscodeType> transcodeClass;
	//用于跟踪、取消和重新启动正在进行的、已完成的和失败的请求的类。
    protected final RequestTracker requestTracker;
	//生命周期
    protected final Lifecycle lifecycle;
	//磁盘缓存策略,只保存处理后的结果。
    private DiskCacheStrategy diskCacheStrategy = DiskCacheStrategy.RESULT;
	//设置的transformation
    private Transformation<ResourceType> transformation = UnitTransformation.get();
	//占位图id
    private int placeholderId;
	//失败图id
    private int errorId;
	...

以上通过load()方法,将网络,或者本地的资源,封装成一个GenericRequestBuilder 实例。

接下来是最后一个方法into(), 是绑定target对象。将前面要展示的资源,与要显示的载体绑定。这一步也是不可或缺的,一起分析下绑定流程。

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

直接看下父类是怎么生成target对象的。

    /**
     * 设置资源加载的ImageView,会取消一切当前存在的加载,释放任何先前已经加载到View上的资源,以便可以复用。
     * @see Glide#clear(android.view.View)
     *
     * @param view 取消view身上之前设置的的下载,加载新的下载。
     * @return Target 是传入的view的封装。
     */
    public Target<TranscodeType> into(ImageView view) {
        Util.assertMainThread();
        if (view == null) {
            throw new IllegalArgumentException("You must pass in a non null View");
        }

        if (!isTransformationSet && view.getScaleType() != null) {
		//如果设置过ImageView的scaleType
            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));
    }

 

执行到最下面一行,继续跟进去。

return into(glide.buildImageViewTarget(view, transcodeClass));

glide.buildImageViewTarget(view, transcodeClass)  对View做了一些封装,比如 在开始下载的时候,先展示默认图。这里就不一起看了,可以自己点进去看看,继续主流程。

    /**
     * 设置target要展示的图片资源。
     */
    public <Y extends Target<TranscodeType>> 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())");
        }
        //先判断当前target有没有被设置过request
        Request previous = target.getRequest();

        if (previous != null) {
        //复用的target,释放资源。
            previous.clear();
            requestTracker.removeRequest(previous);
            previous.recycle();
        }
        //给target重新设置request
        Request request = buildRequest(target);
        target.setRequest(request);
        //添加声明周期方法,保证fragment声明周期回调时,request做出相应的处理。
        lifecycle.addListener(target);
        //开启请求
        requestTracker.runRequest(request);
       
        return target;
    }

这里要注意,对复用类型的 target首先判断之前有没有设置过request。设置的方式实际上是通过view.setTag()来实现的。

因此,在我们使用Glide的时候, 要注意,不要自己调用 view.setTag() 否则会报错 。

java.lang.IllegalArgumentException: You must not call setTag() on a view Glide is targeting

接下来就重点看下请求怎么发起的,request的发起,暂停,移除,恢复request都由RequestTrackerjia 间接管理。

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

实际上调用的就是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));
        }
    }

不论是重新指定过宽高还是使用target的默认宽高,最终都会回调到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<T> 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));
        }
        loadedFromMemoryCache = true;
        //交给Engine去获取资源
        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));
        }
    }

接下来执行到engine.laod() 方法。这个方法是根据传递的参数去开启资源加载。

流程如下:
    1.从memorycache中检索资源,如果内存中有缓存资源,使用内存中的缓存。
     2.检索当前使用的活跃资源(ActiveResources),如果检索到。使用当前活跃的。
    ActiveResources也是内存缓存策略中的,只要是正在使用的缓存,都是加入到ActiveResource中的,ActiveResource核心是维护了一个弱引用的Map来储存对应的缓存数据
     3.从当前正在进行加载的任务集合中查找,如果前面已经添加进加载队列,那么直接使用。
    4.开始一个新的下载。
         
    内存缓存策略:使用了两级内存缓存,MemoryCache和ActiveResource,前者默认为一个LruResourceCache,
    后者是一个Map弱引用,引用了从MemoryCache中读取过的资源和从网络、硬盘下载和转换出的资源。
    加载图片时先使用MemoryCache,如果没有找到则尝试从ActiveResource中获取资源。如果还是没有再从磁盘、网络获取资源。

   /**
     * Starts a load for the given arguments. Must be called on the main thread.
     *根据给定的参数去开启资源加载,这个方法工作在主线程。
     */
    public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,
            DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder,
            Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
        Util.assertMainThread();
        long startTime = LogTime.getLogTime();

        final String id = fetcher.getId();
        //根据签名、宽高、transformation等等信息对要加载的资源生成一个唯一的key。
        EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
                loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
                transcoder, loadProvider.getSourceEncoder());
        //1.从内存中获取,isMemoryCacheable:是否允许内存缓存策略
        EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
        if (cached != null) {
            cb.onResourceReady(cached);
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                logWithTimeAndKey("Loaded resource from cache", startTime, key);
            }
            return null;
        }
        //2.从activeResources中获取 isMemoryCacheable:是否允许内存缓存策略
        EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
        if (active != null) {
            cb.onResourceReady(active);
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                logWithTimeAndKey("Loaded resource from active resources", startTime, key);
            }
            return null;
        }
        //3.是否之前已经添加了该任务。
        EngineJob current = jobs.get(key);
        if (current != null) {
            current.addCallback(cb);
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                logWithTimeAndKey("Added to existing load", startTime, key);
            }
            return new LoadStatus(cb, current);
        }
        //4.执行到这里,说明要新建任务了。engineJobFactory.build()
        EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);
        DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,
                transcoder, diskCacheProvider, diskCacheStrategy, priority);
        //将任务添加到集合中。 Map<Key, EngineJob> jobs
        jobs.put(key, engineJob);
        engineJob.addCallback(cb);
        //启动任务start();
        engineJob.start(runnable);

        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            logWithTimeAndKey("Started new load", startTime, key);
        }
        return new LoadStatus(cb, engineJob);
    }
	
    /**
     *1.从内存中获取。
     */
    private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) {
        //不允许内存缓存 直接返回
        if (!isMemoryCacheable) {
            return null;
        }
        //尝试从内存中获取
        EngineResource<?> cached = getEngineResourceFromCache(key);
        if (cached != null) {
            //从内存中获取到
            cached.acquire();
            //加入到activeResources集合。activeResources = new HashMap<Key, WeakReference<EngineResource<?>>>();
            activeResources.put(key, new ResourceWeakReference(key, cached, getReferenceQueue()));
        }
        return cached;
    }

	/**
	 *2.从activeResources中获取。
     */
    private EngineResource<?> loadFromActiveResources(Key key, boolean isMemoryCacheable) {
        //不允许内存缓存 直接返回
        if (!isMemoryCacheable) {
            return null;
        }

        EngineResource<?> active = null;
        WeakReference<EngineResource<?>> activeRef = activeResources.get(key);
        if (activeRef != null) {
            //从weakreference中 获取
            active = activeRef.get();
            if (active != null) {
                //没有被回收。
                active.acquire();
            } else {
                activeResources.remove(key);
            }
        }

        return active;
    }

如果缓存中没有,接下来会创建下载任务,开启任务。engineJobFactory.build()创建1个 EngineJob。然后启动

       EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);
        DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,
                transcoder, diskCacheProvider, diskCacheStrategy, priority);
        EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);
        jobs.put(key, engineJob);
        engineJob.addCallback(cb);
        engineJob.start(runnable);

 

public void start(EngineRunnable engineRunnable) {
    this.engineRunnable = engineRunnable;
    future = diskCacheService.submit(engineRunnable);
}

 磁盘线程通过submit提交,后最终执行EngineRunnable 的run方法

    @Override
    public void run() {
        if (isCancelled) {
            return;
        }

        Exception exception = null;
        Resource<?> resource = null;
        try {
            //获取资源
            resource = decode();
        } catch (Exception e) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "Exception decoding", e);
            }
            exception = e;
        }
        //如果已经取消任务,回收资源。
        if (isCancelled) {
            if (resource != null) {
                resource.recycle();
            }
            return;
        }
        //拿到资源后回调
        if (resource == null) {
            onLoadFailed(exception);
        } else {
            onLoadComplete(resource);
        }
    }

主要看下怎么获取资源的,即 decode()方法

    private Resource<?> decode() throws Exception {
        if (isDecodingFromCache()) {
            //从缓存中
            return decodeFromCache();
        } else {
            //从数据源中
            return decodeFromSource();
        }
    }

这里是从数据源获取,我们直接看decodeFromSource();

    private Resource<?> decodeFromSource() throws Exception {
        return decodeJob.decodeFromSource();
    }
    /**
     *对返回的resource 添加transformed 。
     * @throws Exception
     */
    public Resource<Z> decodeFromSource() throws Exception {
        Resource<T> decoded = decodeSource();
        return transformEncodeAndTranscode(decoded);
    }

   

 private Resource<T> decodeSource() throws Exception {
        Resource<T> decoded = null;
        try {
            long startTime = LogTime.getLogTime();
            //请求资源。
            final A data = fetcher.loadData(priority);
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                logWithTimeAndKey("Fetched data", startTime);
            }
            if (isCancelled) {
                return null;
            }
            //
            decoded = decodeFromSourceData(data);
        } finally {
            fetcher.cleanup();
        }
        return decoded;
    }


    
 

   @Override
    public InputStream loadData(Priority priority) throws Exception {
        return loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/, glideUrl.getHeaders());
    }

      

     private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl, Map<String, String> headers)
            throws IOException {
        if (redirects >= MAXIMUM_REDIRECTS) {
            throw new IOException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
        } else {
            // Comparing the URLs using .equals performs additional network I/O and is generally broken.
            // See http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html.
            try {
                if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
                    throw new IOException("In re-direct loop");
                }
            } catch (URISyntaxException e) {
                // Do nothing, this is best effort.
            }
        }
        //使用的是HttpUrlConnection
        urlConnection = connectionFactory.build(url);
        for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
          urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
        }
        //连接时间,超时时间。
        urlConnection.setConnectTimeout(2500);
        urlConnection.setReadTimeout(2500);
        urlConnection.setUseCaches(false);
        urlConnection.setDoInput(true);

        // Connect explicitly to avoid errors in decoders if connection fails.
        urlConnection.connect();
        if (isCancelled) {
            return null;
        }
        final int statusCode = urlConnection.getResponseCode();
        if (statusCode / 100 == 2) {
            //200 请求成功
            return getStreamForSuccessfulRequest(urlConnection);
        } else if (statusCode / 100 == 3) {
            String redirectUrlString = urlConnection.getHeaderField("Location");
            if (TextUtils.isEmpty(redirectUrlString)) {
                throw new IOException("Received empty or null redirect url");
            }
            URL redirectUrl = new URL(url, redirectUrlString);
            return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
        } else {
            if (statusCode == -1) {
                throw new IOException("Unable to retrieve response code from HttpUrlConnection.");
            }
            throw new IOException("Request failed " + statusCode + ": " + urlConnection.getResponseMessage());
        }
    }
    //返回inputStream
    private InputStream getStreamForSuccessfulRequest(HttpURLConnection urlConnection)
            throws IOException {
        if (TextUtils.isEmpty(urlConnection.getContentEncoding())) {
            int contentLength = urlConnection.getContentLength();
            stream = ContentLengthInputStream.obtain(urlConnection.getInputStream(), contentLength);
        } else {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "Got non empty content encoding: " + urlConnection.getContentEncoding());
            }
            stream = urlConnection.getInputStream();
        }
        return stream;
    }

 

    //对InputStream封装成 Bitmap资源。
    private Resource<T> decodeFromSourceData(A data) throws IOException {
        final Resource<T> decoded;
        if (diskCacheStrategy.cacheSource()) {
        //缓存源数据
            decoded = cacheAndDecodeSourceData(data);
        } else {
            long startTime = LogTime.getLogTime();
            //包装数据。
            decoded = loadProvider.getSourceDecoder().decode(data, width, height);
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                logWithTimeAndKey("Decoded from source", startTime);
            }
        }
        return decoded;
    }

 

    
    再回到前面的decodeFromSource()方法,将 resource 进行缓存。
    private Resource<Z> transformEncodeAndTranscode(Resource<T> decoded) {
        long startTime = LogTime.getLogTime();
        Resource<T> transformed = transform(decoded);
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            logWithTimeAndKey("Transformed resource from source", startTime);
        }

        writeTransformedToCache(transformed);

        startTime = LogTime.getLogTime();
        Resource<Z> result = transcode(transformed);
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            logWithTimeAndKey("Transcoded transformed from source", startTime);
        }
        return result;
    }

这样,从发起request到获取到resource的流程就完成了。整个流程就是对最开始一张图的分析。

 

再来总结一下:

1.with(context):传入上下文对象,Glide内部 根据上下文的类型,来创建RequestManager。request的生命周期,受传入的context参数影响,如果传递的是application类型的,那么request的生命周期跟随应用走,如果是activity,或者fragment,那么生命周期与传入activity,或者fragment的生命周期保持一致。如果Activity/Fragment 被销毁,request 也会被cancel。

2.load(url): 根据url资源封装一个来返回drawable或者Bitmap drawable的request对象。

3.into(target):传入要承载resource 的target对象。先判断target有没有被复用过,如果复用过,先回收target身上设置过的request info,然后重新设置新的request info.设置的方式是通过view.setTag()所以,使用Glide加载图片的时候,我们不要自己调用setTag()方法,否则会报错。java.lang.IllegalArgumentException: You must not call setTag() on a view Glide is targeting。
设置完request info 后,会启动request,获取resource,获取的策略优先级是memorycache->activeRearource->diskcache-> netWork。
    

或许你还有疑问,后面会继续看以下几个问题。

Glide 中线程池用大小?
Bitmap如何复用的? Bitmappool。
发起request 拿到的 resource 如何缓存的。?
Glide缓存机制 内存 磁盘?
Glide中的设计模式?

https://muyangmin.github.io/glide-docs-cn/
​​​​​​​​​​​​​​http://www.paincker.com/glide-study​​​​​​​
https://blog.csdn.net/u012124438/article/details/73612492
https://www.cnblogs.com/android-blogs/p/5735655.html
https://blog.csdn.net/guolin_blog/article/details/53939176
https://segmentfault.com/a/1190000014853308

 谢谢认真观读本文的每一位小伙伴,衷心欢迎小伙伴给我指出文中的错误,也欢迎小伙伴与我交流学习。

 欢迎爱学习的小伙伴加群一起进步:230274309 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值