Glide源码分析

直接进入主题

当前使用的glide版本为3.7.0

正常请求加载图片代码如下:

	String url = "http://www.baidu.com";
	Glide.with(getApplicationContext()) //指定Content
            .load(url) //指定图片的url
            .placeholder(R.mipmap.ic_launcher)//指定图片未成功加载前的默认图片
            .error(R.mipmap.ic_launcher) //指定图片加载失败之后的图片
            .override(300,300)//指定图片的宽高
            .fitCenter()//指定图片的缩放类型为fitCenter(宽高小于等于ImageView的宽高,等比例缩放)
            .centerCrop()//指定图片的缩放类型为centerCrop(会完整显示,但是可能会显示不全)
            .skipMemoryCache(true)//跳过内存缓存,不会把该图片放到内存缓存,默认为false
            .diskCacheStrategy(DiskCacheStrategy.NONE)//跳过磁盘缓存
            .diskCacheStrategy(DiskCacheStrategy.SOURCE)//仅仅只缓存原来的全分辨率的图像
            .diskCacheStrategy(DiskCacheStrategy.RESULT)//仅仅缓存最终的图像
            .diskCacheStrategy(DiskCacheStrategy.ALL)//缓存所有版本的图像,包括前两个
            .priority(Priority.HIGH)//指定优先级,Glide将会用它们作为一个准则,并尽可能的处理这些请求,并不一定百分百实施
            .into(imageView);//指定显示图片的ImageView

with方法

进入with方法查看源码发现有很多get方法重载有activity,Fragment,FragmentActivity,context ,这样做的目的是为了跟不同组件的生命周期所挂钩,来处理图片请求的逻辑,拿context举例

public static RequestManager with(Context context) {
    RequestManagerRetriever retriever = RequestManagerRetriever.get();  //RequestManagerRetriever用来生成RequestManager,而equestManager则负责管理图片请求
    return retriever.get(context);
}

public RequestManager get(Context context) {
    if (context == null) {//如果context为空就会抛异常
        throw new IllegalArgumentException("You cannot start a load on a null Context");
    } else {
        if (Util.isOnMainThread() && !(context instanceof Application)) {//判断是否是在主线程,判断传入的context是否是这个应用的实例
            if (context instanceof FragmentActivity) {
                return this.get((FragmentActivity)context);
            }
            if (context instanceof Activity) {
                return this.get((Activity)context);
            }
            if (context instanceof ContextWrapper) {
                return this.get(((ContextWrapper)context).getBaseContext());
            }
        }

        return this.getApplicationManager(context);//获取单例
    }
}
//当使用getApplicationContext()
private RequestManager getApplicationManager(Context context) { //通过单例获取唯一一个applicationManager
    if (this.applicationManager == null) {
        synchronized(this) {
            if (this.applicationManager == null) {
                this.applicationManager = new RequestManager(context.getApplicationContext(), new ApplicationLifecycle(), new EmptyRequestManagerTreeNode());
            }
        }
    }
    return this.applicationManager;
}
//当使用Activity
public RequestManager get(Activity activity) {
    if (!Util.isOnBackgroundThread() && VERSION.SDK_INT >= 11) {//判断当前线程不是后台进行
        assertNotDestroyed(activity);
        FragmentManager fm = activity.getFragmentManager();//获取FragmentManager
        return this.fragmentGet(activity, fm); //	
    } else {
        return this.get(activity.getApplicationContext());  //否则进入上一个方法RequestManager get()
    }
}

RequestManager fragmentGet(Context context, FragmentManager fm) {
    RequestManagerFragment current = this.getRequestManagerFragment(fm);//获取RequestManagerFragment 添加一种没有UI的fragment来监听生命周期
    RequestManager requestManager = current.getRequestManager(); //根据创建好的RequestManagerFragment 来创建RequestManager
    if (requestManager == null) {
        requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());//看到lifecycle()就知道有生命周期的管理
        current.setRequestManager(requestManager);//将RequestManagerFragment与RequestManager进行绑定,主要目的是通过监听fragment的生命周期来管理整个图片加载
    }
    return requestManager;
}

RequestManagerFragment 如何与RequestManager建立生命周期的?

RequestManagerFragment .java

private final ActivityFragmentLifecycle lifecycle;
public void onStart() {
    super.onStart();
    this.lifecycle.onStart();
}
public void onStop() {
    super.onStop();
    this.lifecycle.onStop();
}
public void onDestroy() {
    super.onDestroy();
    this.lifecycle.onDestroy();
}

其实是通过lifecycle 来监听生命周期,通过生命周期执行lifecycle接口来传递生命周期

总结:with流程,通过RequestManagerRetriever来获取RequestManager然后get方法获取RequestManagerFragment,这个Fragment不需要ui的,并通过lifecycle来管理生命周期,这样做的目的是为了glide本身不知道activity的生命周期增加管理生命周期起到的作用,比如当前页面关闭了,但是之前正在加载图片的glide需要停止下载就会通过监听生命周期来操作,这样就节省了图片资源。

load方法

//RequestManager.java  
public DrawableTypeRequest<byte[]> load(byte[] model) {
    return (DrawableTypeRequest)this.fromBytes().load(model);//通过DrawableTypeRequest 获取到图片请求Request
}
//DrawableRequestBuilder.java
public DrawableRequestBuilder<ModelType> load(ModelType model) {
    super.load(model);
    return this;
}
//GenericRequestBuilder.java
public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> load(ModelType model) {
    this.model = model;  //初始化操作
    this.isModelSet = true;
    return this;
}

其实load方法也是做了一些初始化操作,通过DrawableTypeRequest 来获取加载图片请求request 继而后续into操作

into方法

//GenericRequestBuilder.java 

public Target<GlideDrawable> into(ImageView view) {
    return super.into(view);
}
public Target<TranscodeType> into(ImageView view) {//进行图片加载
    Util.assertMainThread();//判断当前是否在主线程当中
    if (view == null) {//判断imageview是否为空
        throw new IllegalArgumentException("You must pass in a non null View");
    } else {
        if (!this.isTransformationSet && view.getScaleType() != null) {
            switch(view.getScaleType()) {//对图片进行裁剪
            case CENTER_CROP: 	
                this.applyCenterCrop();
                break;
            case FIT_CENTER:
            case FIT_START:
            case FIT_END:
                this.applyFitCenter();
            }
        }
        return this.into(this.glide.buildImageViewTarget(view, this.transcodeClass));//提供一个所需要的target
    }
}	

public static void assertMainThread() {
    if (!isOnMainThread()) {//如果不是在主线程就会抛出异常
        throw new IllegalArgumentException("You must call this method on the main thread");
    }
}
public interface Target<R> extends LifecycleListener { //实现LifecycleListener 监听生命周期
    int SIZE_ORIGINAL = -2147483648;

    void onLoadStarted(Drawable var1);

    void onLoadFailed(Exception var1, Drawable var2);

    void onResourceReady(R var1, GlideAnimation<? super R> var2);

    void onLoadCleared(Drawable var1);

    void getSize(SizeReadyCallback var1);

    void setRequest(Request var1);

    Request getRequest();
}
public interface LifecycleListener { //通过这个接口监听生命周期
    void onStart();

    void onStop();

    void onDestroy();
}
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");
    } else if (!this.isModelSet) {
        throw new IllegalArgumentException("You must first set a model (try #load())");
    } else {
        Request previous = target.getRequest(); //获取当前的Target绑定的Request的对象
        if (previous != null) {
            previous.clear(); //清除
            this.requestTracker.removeRequest(previous);//把之前的Request暂停
            previous.recycle();//复用
        }
        Request request = this.buildRequest(target);//如果之前的为空的话创建新的Request
        target.setRequest(request);//将target与Request绑定防止错位
        this.lifecycle.addListener(target);
        this.requestTracker.runRequest(request);//执行runRequest 请求
        return target;
    }
}
//RequestTracker.java

 private final Set<Request> requests = Collections.newSetFromMap(new WeakHashMap());
 public void runRequest(Request request) {
        this.requests.add(request);//把request放到set集合当中
        if (!this.isPaused) {//如果当前request正在请求的话
            request.begin();
        } else {
            this.pendingRequests.add(request);
        }
    }
	
//GenericRequest.java

public void begin() {
    this.startTime = LogTime.getLogTime();
    if (this.model == null) {
        this.onException((Exception)null);
    } else {
        this.status = GenericRequest.Status.WAITING_FOR_SIZE;
        if (Util.isValidDimensions(this.overrideWidth, this.overrideHeight)) {//如果知道overide方法就会通过该判断
            this.onSizeReady(this.overrideWidth, this.overrideHeight);
        } else {
            this.target.getSize(this);//重新计算宽高
        }
        if (!this.isComplete() && !this.isFailed() && this.canNotifyStatusChanged()) {//当前是否已经完成了,并且成功了
            this.target.onLoadStarted(this.getPlaceholderDrawable());//设定图片
        }
        if (Log.isLoggable("GenericRequest", 2)) {
            this.logV("finished run method in " + LogTime.getElapsedMillis(this.startTime));
        }
    }
}	
	
	
	public void getSize(SizeReadyCallback cb) {
        this.sizeDeterminer.getSize(cb);
    }
	
	public void getSize(SizeReadyCallback cb) {
        int currentWidth = this.getViewWidthOrParam();//获取宽
        int currentHeight = this.getViewHeightOrParam();//获取高
        if (this.isSizeValid(currentWidth) && this.isSizeValid(currentHeight)) {//view绘制完成
            cb.onSizeReady(currentWidth, currentHeight);//还是会走onSizeReady
        } else {
            if (!this.cbs.contains(cb)) {
                this.cbs.add(cb);
            }
            if (this.layoutListener == null) { //当前的view还没有测量完毕
                ViewTreeObserver observer = this.view.getViewTreeObserver();//去绘制view
                this.layoutListener = new ViewTarget.SizeDeterminer.SizeDeterminerLayoutListener(this);
                observer.addOnPreDrawListener(this.layoutListener);
            }
        }
    }

总结:第一步创建我们需要的request,然后发送request给requestTracker来进行,通过requestTracker的begin方法来对图片进行判断,如果执行过override方法就会直接进行onSizeReady,否则就会邹getsize方法去对view重新的测量
接下来看一下onSizeReady方法

public void onSizeReady(int width, int height) {
    if (Log.isLoggable("GenericRequest", 2)) {
		this.logV("Got onSizeReady in " + LogTime.getElapsedMillis(this.startTime));
    }
    if (this.status == GenericRequest.Status.WAITING_FOR_SIZE) {
        this.status = GenericRequest.Status.RUNNING;
        width = Math.round(this.sizeMultiplier * (float)width);
        height = Math.round(this.sizeMultiplier * (float)height);
        ModelLoader<A, T> modelLoader = this.loadProvider.getModelLoader();//负责从数据源中获取原始数据
        DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(this.model, width, height);//将原始数据转成直接用的不同类型的图片数据类型
        if (dataFetcher == null) {
            this.onException(new Exception("Failed to load model: '" + this.model + "'"));
        } else {
            ResourceTranscoder<Z, R> transcoder = this.loadProvider.getTranscoder();//对原始数据解码,负责将得到的原始数据解码成bitmap
            if (Log.isLoggable("GenericRequest", 2)) {
                this.logV("finished setup for calling load in " + LogTime.getElapsedMillis(this.startTime));
            }
            this.loadedFromMemoryCache = true;
			//该方法是图片加载的全过程
            this.loadStatus = this.engine.load(this.signature, width, height, dataFetcher, this.loadProvider, this.transformation, transcoder, this.priority, this.isMemoryCacheable, this.diskCacheStrategy, this);
            this.loadedFromMemoryCache = this.resource != null;
            if (Log.isLoggable("GenericRequest", 2)) {
                this.logV("finished onSizeReady in " + LogTime.getElapsedMillis(this.startTime));
            }
        }
    }
}
Engine.java
	
	public <T, Z, R> Engine.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();
        String id = fetcher.getId();//获取到加载图片的唯一表示
		//glide缓存的key
        EngineKey key = this.keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(), loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(), transcoder, loadProvider.getSourceEncoder());
        EngineResource<?> cached = this.loadFromCache(key, isMemoryCacheable);//从缓存中获取图片(最近使用过的图片,LruCache算法使用linkHashMap缓存)
        if (cached != null) {
            cb.onResourceReady(cached);//
            if (Log.isLoggable("Engine", 2)) {
                logWithTimeAndKey("Loaded resource from cache", startTime, key);
            }

            return null;
        } else {
            EngineResource<?> active = this.loadFromActiveResources(key, isMemoryCacheable);//获取缓存图片(保存当前正在使用的EngineResource弱引起对象,其实  activeResources就是HashMap)
            if (active != null) {
                cb.onResourceReady(active);
                if (Log.isLoggable("Engine", 2)) {
                    logWithTimeAndKey("Loaded resource from active resources", startTime, key);
                }

                return null;
            } else {
                EngineJob current = (EngineJob)this.jobs.get(key);//去从磁盘或者网络获取图片
                if (current != null) {
                    current.addCallback(cb);
                    if (Log.isLoggable("Engine", 2)) {
                        logWithTimeAndKey("Added to existing load", startTime, key);
                    }

                    return new Engine.LoadStatus(cb, current);
                } else {
                    EngineJob engineJob = this.engineJobFactory.build(key, isMemoryCacheable);
                    DecodeJob<T, Z, R> decodeJob = new DecodeJob(key, width, height, fetcher, loadProvider, transformation, transcoder, this.diskCacheProvider, diskCacheStrategy, priority);
                    EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);
                    this.jobs.put(key, engineJob);
                    engineJob.addCallback(cb);
                    engineJob.start(runnable);
                    if (Log.isLoggable("Engine", 2)) {
                        logWithTimeAndKey("Started new load", startTime, key);
                    }

                    return new Engine.LoadStatus(cb, engineJob);
                }
            }
        }
    }

private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) {
        if (!isMemoryCacheable) {//默认为true ,默认开启内存缓存的
            return null;
        } else {
            EngineResource<?> cached = this.getEngineResourceFromCache(key);//
            if (cached != null) {
                cached.acquire();
                this.activeResources.put(key, new Engine.ResourceWeakReference(key, cached, this.getReferenceQueue()));//写入缓存
            }

            return cached;
        }
    }
	
	
	private EngineResource<?> loadFromActiveResources(Key key, boolean isMemoryCacheable) {
        if (!isMemoryCacheable) {
            return null;
        } else {
            EngineResource<?> active = null;
            WeakReference<EngineResource<?>> activeRef = (WeakReference)this.activeResources.get(key); //弱引用
            if (activeRef != null) {
                active = (EngineResource)activeRef.get();
                if (active != null) {
                    active.acquire();
                } else {
                    this.activeResources.remove(key);
                }
            }

            return active;
        }
    }

总结:首先loadFromCache会去从内存缓存中去读取需要加载的图片如果有直接执行回调onResourceReady ,如果获取不到图片就会执行loadFromActiveResources,表明这个图片在缓存中没有,看一下正在使用的这些图片会不会有,如果有的话就会返回回调onResourceReady,如果这两种情况下都没有,才会创建一个EngineJob去加载我们需要的图片
那么内存缓存从哪里写入的

EngineJob.java
private static final Handler MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper(), new EngineJob.MainThreadCallback());
public void onResourceReady(Resource<?> resource) {
        this.resource = resource;
        MAIN_THREAD_HANDLER.obtainMessage(1, this).sendToTarget();
}
由上可知实现是在MainThreadCallback当中

 private static class MainThreadCallback implements Callback {
        private MainThreadCallback() {
        }

        public boolean handleMessage(Message message) {
            if (1 != message.what && 2 != message.what) {
                return false;
            } else {
                EngineJob job = (EngineJob)message.obj;
                if (1 == message.what) {
                    job.handleResultOnMainThread(); //会在主线程实现接口的回调
                } else {
                    job.handleExceptionOnMainThread();
                }

                return true;
            }
        }
    }
	
	private void handleResultOnMainThread() {
        if (this.isCancelled) { //如果任务取消的话
            this.resource.recycle();//需要回收资源
        } else if (this.cbs.isEmpty()) {//如果任务没有取消的话,cbs为空就会抛出异常
            throw new IllegalStateException("Received a resource without any callbacks to notify");
        } else {
            this.engineResource = this.engineResourceFactory.build(this.resource, this.isCacheable);
            this.hasResource = true;
            this.engineResource.acquire();
            this.listener.onEngineJobComplete(this.key, this.engineResource);
            Iterator i$ = this.cbs.iterator();

            while(i$.hasNext()) {
                ResourceCallback cb = (ResourceCallback)i$.next();
                if (!this.isInIgnoredCallbacks(cb)) {
                    this.engineResource.acquire();
                    cb.onResourceReady(this.engineResource);
                }
            }

            this.engineResource.release();//通过该方法,如果正在图片正在使用的话会存入弱引用当中,如果不在使用的话就会存在LruCache当中
        }
    }
public void onResourceReleased(Key cacheKey, EngineResource resource) {
    Util.assertMainThread();
    this.activeResources.remove(cacheKey);//把整个activeResources删除了
    if (resource.isCacheable()) { 
        this.cache.put(cacheKey, resource);//然后加入到Lrucache当中
    } else {
        this.resourceRecycler.recycle(resource);
    }
}
 public void onEngineJobComplete(Key key, EngineResource<?> resource) {
    Util.assertMainThread();
    if (resource != null) {
        resource.setResourceListener(key, this);
        if (resource.isCacheable()) {
            this.activeResources.put(key, new Engine.ResourceWeakReference(key, resource, this.getReferenceQueue()));//写入 并且是弱引用
        }
    }

    this.jobs.remove(key);
}

总结:glide内存缓存的实现首先loadFromCache会去从内存缓存中去读取需要加载的图片如果有直接执行回调onResourceReady ,如果获取不到图片就会执行loadFromActiveResources,表明这个图片在缓存中没有,看一下正在使用的这些图片会不会有,如果有的话就会返回回调onResourceReady,如果这两种情况下都没有,才会创建一个EngineJob去从磁盘或者网络上获取。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万子开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值