几个核心类简介:
DataFetcher 从不同的地方拉去数据,是一个接口,
实现类,负责拉取
EngineRunnable 负责组合各功能对象,组织加载 类
ResourceDecoder 负责资源解码接口,StreamBitmapDecoder 子类,负责解析流
ResourceEncoder 负责资源编码
DataLoadProvider 接口,里面可以获取必要的编码和节码类ResourceDecoder ,ResourceEncoder
BitmapDecoder 接口,负责从一个资源解析成Bitmap 实现类Downsampler,从流解析成Bitmap
Downsampler 是抽象类,里面又很多,静态内部成员变量,负责具体的,解析
BitmapResource 对Bitmap的包装,可以获取Bitmap,并且返回大小,可以释放bitmap
ResourceCallback 资源加载回调
Engine 中的load 方法是开始,
load方法,再GenericRequest 中的onSizeReady中调用
GenericRequest 会注册ResourceCallback ,SizeReadyCallback,回调,并且负责RequestListener回调和Target回调
SizeReadyCallback,再大小固定轴回调
ViewTarget 中有一个对象SizeDeterminer
SizeDeterminer 负责确定View的大小 SizeDeterminer 接受一个View参数,然后再内部注册
ViewTreeObserver observer = view.getViewTreeObserver();
if (observer.isAlive()) {
observer.removeOnPreDrawListener(layoutListener);
}
监听绘制完成的回调,SizeDeterminer 中会收集SizeReadyCallback监听的集合,然后再绘制完成的监听中,通知SizeReadyCallback,的方法,然后久通知到了Engine 的init
Target的getSize()会调用SizeDeterminer 的getSize()
SizeDeterminer 的getSize()中会先判断View和宽度和高度是否有效,如果无效,也会注册监听
Target.....beigin.......getSize().....然后再SizeReadyCallback的。-------onSizeReady(int width, int height);-----------Engine.load()
DrawableTypeRequest 继承自DrawableRequestBuilder 负责很多默认对象的填充,例如ModelLoader ,
EngineJob 负责执行EngineRunnable 并且也负责ResourceCallback 回调
内部有缓存线程池,执行EngineRunnable 的线程池,并且注册了监听到EngineRunnable ,
EngineRunnable 把执行结果,通过回调EngineRunnable.EngineRunnableManager
给EngineJob ,EngineJob 再回调给ResourceCallback ,并且管理失败的EngineRunnable
EngineResource 包装了resource ,还包装了一个回调
ModelLoader 负责,根据宽高和model,找到对应数据加载DataFetcher
Glide.with(mContext).pauseRequests();
Glide.with(mContext)
//.using(null) //这个方法是设置自己的资源拉取器 ModelLoader<A, T> modelLoader, Class<T> dataClass
//可以只定义资源拉取,也可以定义LoadProvider中的所有内容,定义,从资源下载,解码,转换,图片变换的所有过程
.fromString()
.load(path)
.animate(0)//设置动画
.transform(new CenterCrop(mContext))//设置图片变换可以设置多个
.skipMemoryCache(false)//可以跳过
.diskCacheStrategy(DiskCacheStrategy.ALL)
.centerCrop() //按比例缩放填充控件,再内部会转化为transform,所以如果也需要其他转换,请自己实现这个,然后一起设置
.error(0)//加载错误图片显示
.placeholder(0)//加载中占位符
.fallback(0)//如果数据model设置的null,就会显示这个图片,否则会报错
.listener(new RequestListener<String, GlideDrawable>() {
@Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
return false;
}
})
//下面能再这里设置,然后替换掉,原来创建的原因,主要再ChildLoadProvider类
//.sourceEncoder() //替换从Factory 中创建的源文件,编码器,编码成流
// .cacheDecoder()//从缓存文件中,解码成图片资源 从File 解码成GifBitmapWrapper 替换Factory中创建的
//.decoder() //可以再这里设置资源解码器,替换按照类型,从Factory中创建的 从ImageVideoWrapper
// (inputStream 和ParcelFileDescriptor)的包装类,解码成GifBitmapWrapper
// .encoder() //可以再这里设置,替换上面按照类型,从Factory中取的 把资源编码成输出流
.priority(Priority.NORMAL)
.into(mImageView);
Glide.with(mContext);
Glide. public static RequestManager with(Context context) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();//从RequestManagerRetriever(RequestManager的管理者,负责activity,Fragment,和RequestManager的对应)
return retriever.get(context);//从RequestManagerRetriever 中找到和上下文,对应的RequestManager
}
RequestManger,主要负责构建RequstBuilder ,负责感受上下文生命周期的回调,然后通过RequestTracker 管理Request的生命周期
-》 RequestManger.fromString() //生成DrawableTypeRequest 是GenericRequestBuilder的非直接子类,主要负责,数据model 类型,数据类型,资源类型 ,转化后类型
//再确定使用那种类型的,ModelLoader,ResourceDecoder,ResourceTranscoder,并且通过我们传递的参数,构建Request
-》 .animate(0)//设置动画
.transform(new CenterCrop(mContext))//设置图片变换可以设置多个
.skipMemoryCache(false)//可以跳过
.diskCacheStrategy(DiskCacheStrategy.ALL)
.centerCrop() //按比例缩放填充控件,再内部会转化为transform,所以如果也需要其他转换,请自己实现这个,然后一起设置
.error(0)//加载错误图片显示
.placeholder(0)//加载中占位符
.fallback(0)//如果数据model设置的null,就会显示这个图片,否则会报错
.listener(new RequestListener<String, GlideDrawable>() {
@Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
return false;
}
})
//下面能再这里设置,然后替换掉,原来创建的原因,主要再ChildLoadProvider类
//.sourceEncoder() //替换从Factory 中创建的源文件,编码器,编码成流
// .cacheDecoder()//从缓存文件中,解码成图片资源 从File 解码成GifBitmapWrapper 替换Factory中创建的
//.decoder() //可以再这里设置资源解码器,替换按照类型,从Factory中创建的 从ImageVideoWrapper
// (inputStream 和ParcelFileDescriptor)的包装类,解码成GifBitmapWrapper
// .encoder() //可以再这里设置,替换上面按照类型,从Factory中取的 把资源编码成输出流
.priority(Priority.NORMAL)//设置请求的优先级,会影响请求的排序
上面的设置,都设置到GenericRequestBuilder或者它的子类中,用来构建Request
-》 .into(mImageView);
@Override
DrawableRequestBuilder. public Target<GlideDrawable> into(ImageView view) {
return super.into(view);
}
-》 super.into(view);
GenericRequestBuilder.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) {//如果没有自己设置Transformation,就会根据View的ScaleType设置对应的Transformation
switch (view.getScaleType()) {
case CENTER_CROP:
applyCenterCrop(); //Transformation
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
applyFitCenter();//Transformation
break;
//$CASES-OMITTED$
default:
// Do nothing.
}
}
return into(glide.buildImageViewTarget(view, transcodeClass));
}
-》glide.buildImageViewTarget(view, transcodeClass) 根据View和转换后数据的类型,获取对应Target 获取到GlideDrawableImageViewTarget
-》 into(glide.buildImageViewTarget(view, transcodeClass));
GenericRequestBuilder. 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())");
}
Request previous = target.getRequest();//获取Target之前的Request
if (previous != null) {
previous.clear(); //清空资源
requestTracker.removeRequest(previous);//从移除request
previous.recycle(); //把请循环
}
Request request = buildRequest(target);//构建请求
target.setRequest(request); //请求设置到target
lifecycle.addListener(target); //为Target添加感应上下文的生命周期
requestTracker.runRequest(request); //开始运行Request
return target;
}
-》Request request = buildRequest(target);
GenericRequestBuilder. private Request buildRequest(Target<TranscodeType> target) {
if (priority == null) {
priority = Priority.NORMAL;
}
return buildRequestRecursive(target, null);
}
-》GenericRequestBuilder. buildRequestRecursive(target, null);
GenericRequestBuilder. private Request buildRequestRecursive(Target<TranscodeType> 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);//创建一个Request
}
}
-》 GenericRequestBuilder. obtainRequest(target, sizeMultiplier, priority, parentCoordinator);//创建一个Request
GenericRequestBuilder. private Request obtainRequest(Target<TranscodeType> 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);
}
-》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);
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<R> 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<Z> transformation,
Class<R> transcodeClass,
boolean isMemoryCacheable,
GlideAnimationFactory<R> 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) {
request = new GenericRequest<A, T, Z, R>();
}
//为请求设置请求参数
request.init(loadProvider,//提供下载,编码,解码,转换,变换功能
model,//数据model
signature, //签名
context,//上下文
priority,//加载优先级
target,//target相应监听
sizeMultiplier,//支持对资源进行缩放
placeholderDrawable,//加载中占位符
placeholderResourceId,
errorDrawable,//失败占位符
errorResourceId,
fallbackDrawable,//model为null的占位符
fallbackResourceId,
requestListener,//请求的监听
requestCoordinator,
engine,//主要负责执行请求
transformation,//图片变换操作
transcodeClass,//需要转换成的数据类型
isMemoryCacheable,//是否支持使用内存缓存
animationFactory,//动画集合,我们要使用动画,可以自己设置
overrideWidth,//需要的最终的图片宽度
overrideHeight,//需要的最终的图片高度
diskCacheStrategy);//磁盘缓存的策略
return request;
}
-》我们再返回到 requestTracker.runRequest(request); //开始运行Request 之前的设置,都比较简单
public void runRequest(Request request) {
requests.add(request);
if (!isPaused) {
request.begin();//开始执行request
} else {
pendingRequests.add(request);//并把reuqest,加入到记录中
}
}
-》GenericRequest. request.begin();
public void begin() {
startTime = LogTime.getLogTime();
if (model == null) {
onException(null);//如果model是null,会直接走失败,然后把FallbackDrawable设置上去
return;
}
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {//如果设置了固定的有效的宽高,直接执行
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this);//如果没有指定宽度,从target获取高度,并且传递GenericRequest 按照这个走
}
if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable());//执行target中开始回调
}
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished run method in " + LogTime.getElapsedMillis(startTime));
}
}
-》target.getSize(SizeReadyCallback callback); GenericRequest实现了这个回调,再View的宽高确定的时候,回调
接下来,我们分析Target,选择VewTarget分析,因为它的内部,实现监听绘制View之前的一个监听,来获取宽度和高度
public abstract class ViewTarget<T extends View, Z> extends BaseTarget<Z> {
private static final String TAG = "ViewTarget";
private static boolean isTagUsedAtLeastOnce = false;
private static Integer tagId = null;
protected final T view;
private final SizeDeterminer sizeDeterminer; //可以得到,View的宽高
@Override
public void getSize(SizeReadyCallback cb) { //调用这个方法 其实调用的是 sizeDeterminer.getSize(cb);
sizeDeterminer.getSize(cb);
}
/**
* Stores the request using {@link View#setTag(Object)}.
*
* @param request {@inheritDoc}
*/
@Override
public void setRequest(Request request) {
setTag(request);
}
@Override
public Request getRequest() {
Object tag = getTag();
Request request = null;
if (tag != null) {
if (tag instanceof Request) {
request = (Request) tag;
} else {
throw new IllegalArgumentException("You must not call setTag() on a view Glide is targeting");
}
}
return request;
}
private void setTag(Object tag) {
if (tagId == null) {
isTagUsedAtLeastOnce = true;
view.setTag(tag);
} else {
view.setTag(tagId, tag);
}
}
private Object getTag() {
if (tagId == null) {
return view.getTag();
} else {
return view.getTag(tagId);
}
}
@Override
public String toString() {
return "Target for: " + view;
}
}
-》 sizeDeterminer.getSize(cb);
private static class SizeDeterminer {
// Some negative sizes (WRAP_CONTENT) are valid, 0 is never valid.
private static final int PENDING_SIZE = 0;
private final View view;
private final List<SizeReadyCallback> cbs = new ArrayList<SizeReadyCallback>();
private SizeDeterminerLayoutListener layoutListener;
private Point displayDimens;
public SizeDeterminer(View view) {
this.view = view;
}
private void notifyCbs(int width, int height) {
for (SizeReadyCallback cb : cbs) {
cb.onSizeReady(width, height);
}
cbs.clear();
}
private void checkCurrentDimens() {//再监听中执行这个
if (cbs.isEmpty()) {
return;
}
int currentWidth = getViewWidthOrParam();//计算宽度
int currentHeight = getViewHeightOrParam();//计算高度
if (!isSizeValid(currentWidth) || !isSizeValid(currentHeight)) {
return;
}
notifyCbs(currentWidth, currentHeight);//通知回调
// Keep a reference to the layout listener and remove it here
// rather than having the observer remove itself because the observer
// we add the listener to will be almost immediately merged into
// another observer and will therefore never be alive. If we instead
// keep a reference to the listener and remove it here, we get the
// current view tree observer and should succeed.
ViewTreeObserver observer = view.getViewTreeObserver();
if (observer.isAlive()) {
observer.removeOnPreDrawListener(layoutListener);
}
layoutListener = null;
}
public void getSize(SizeReadyCallback cb) { //执行这个方法
int currentWidth = getViewWidthOrParam();
int currentHeight = getViewHeightOrParam();
if (isSizeValid(currentWidth) && isSizeValid(currentHeight)) { //如果是有效的宽高,
cb.onSizeReady(currentWidth, currentHeight); //直接调用回调
} else {//如果没有宽高,
// We want to notify callbacks in the order they were added and we only expect one or two callbacks to
// be added a time, so a List is a reasonable choice.
if (!cbs.contains(cb)) {
cbs.add(cb);
}
if (layoutListener == null) {
final ViewTreeObserver observer = view.getViewTreeObserver();
layoutListener = new SizeDeterminerLayoutListener(this);//设置监听
observer.addOnPreDrawListener(layoutListener);//监听View 绘制之前,然后调用 private void checkCurrentDimens()
}
}
}
private int getViewHeightOrParam() {
final LayoutParams layoutParams = view.getLayoutParams();
if (isSizeValid(view.getHeight())) {
return view.getHeight();
} else if (layoutParams != null) {
return getSizeForParam(layoutParams.height, true /*isHeight*/);
} else {
return PENDING_SIZE;
}
}
private int getViewWidthOrParam() {
final LayoutParams layoutParams = view.getLayoutParams();
if (isSizeValid(view.getWidth())) {
return view.getWidth();
} else if (layoutParams != null) {
return getSizeForParam(layoutParams.width, false /*isHeight*/);
} else {
return PENDING_SIZE;
}
}
private int getSizeForParam(int param, boolean isHeight) {
if (param == LayoutParams.WRAP_CONTENT) {
Point displayDimens = getDisplayDimens();
return isHeight ? displayDimens.y : displayDimens.x;
} else {
return param;
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
@SuppressWarnings("deprecation")
private Point getDisplayDimens() {
if (displayDimens != null) {
return displayDimens;
}
WindowManager windowManager = (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
displayDimens = new Point();
display.getSize(displayDimens);
} else {
displayDimens = new Point(display.getWidth(), display.getHeight());
}
return displayDimens;
}
private boolean isSizeValid(int size) {
return size > 0 || size == LayoutParams.WRAP_CONTENT;
}
private static class SizeDeterminerLayoutListener implements ViewTreeObserver.OnPreDrawListener {//实现View树的回调,监听开始绘制
private final WeakReference<SizeDeterminer> sizeDeterminerRef;
public SizeDeterminerLayoutListener(SizeDeterminer sizeDeterminer) {
sizeDeterminerRef = new WeakReference<SizeDeterminer>(sizeDeterminer);
}
@Override
public boolean onPreDraw() {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "OnGlobalLayoutListener called listener=" + this);
}
SizeDeterminer sizeDeterminer = sizeDeterminerRef.get();
if (sizeDeterminer != null) {
sizeDeterminer.checkCurrentDimens(); //再开始绘制的时候,执行 sizeDeterminer.checkCurrentDimens();
}
return true;
}
}
}
-》执行GenericRequest.onSizeReady(width, height);
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;
loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
priority, isMemoryCacheable, diskCacheStrategy, this);//开始由引擎执行操作,返回loadStatus ,可以取消请求
loadedFromMemoryCache = resource != null;
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
}
-》engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
priority, isMemoryCacheable, diskCacheStrategy, this);//先只分析流程,具体单个细节流程,后面再分析单个方法
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();
EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
transcoder, loadProvider.getSourceEncoder()); //根据信息创建一个key,用于内存缓存,和磁盘缓存
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);//如果允许内存缓存,会从内存缓存中获取,根据key
if (cached != null) {//如果获取到了,直接回调,返回数据
cb.onResourceReady(cached);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);//如可以允许内存缓存,从active(当前正在使用的资源),中获取图片
if (active != null) {//如果获取到了,直接回调,返回数据
cb.onResourceReady(active);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
EngineJob current = jobs.get(key);//获取一个EngineJob ,每一个执行的工作,都会加入到这个map,能获取到对应的,说明正在执行
if (current != null) {
current.addCallback(cb);//如果正在执行,就只是把回回调添加进去
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}
EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);//从engineJobFactory创建一个EngineJob ,负载再内部执行EngineRunnable,然后回调EngineJobListener(Engine实现)
DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,
transcoder, diskCacheProvider, diskCacheStrategy, priority);//创建解码job,负责拉取数据,解码数据,变换数据,转换数据
EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);//具体的执行操作,然后回调EngineRunnable.EngineRunnableManager(EngineJob 实现了这个接口 )
jobs.put(key, engineJob);//把job保存起来
engineJob.addCallback(cb);//把callback,加入到job中,这个cb是回调GenericRequest
engineJob.start(runnable);//开始执行
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Started new load", startTime, key);
}
return new LoadStatus(cb, engineJob);
}
-》 engineJob.start(runnable);//开始执行
public void start(EngineRunnable engineRunnable) {
this.engineRunnable = engineRunnable;
future = diskCacheService.submit(engineRunnable);//Future,用来控制请求,放到子线程去执行engineRunnable.run
}
-》engineRunnable.run
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);//执行失败,回调到engineJob.submitForSource 或者.onException(e)
} else {
onLoadComplete(resource);//执行成功,engineJob.onResourceReady(resource)
}
}
-》分析 resource = engineRunnable.decode();//核心过程
private Resource<?> decode() throws Exception {
if (isDecodingFromCache()) {
return decodeFromCache();//从磁盘缓存中获取 ,先分析从磁盘中获取
} else {
return decodeFromSource();//从数据员拉取
}
}
-》engineRunnable.decodeFromCache();
private Resource<?> decodeFromCache() throws Exception {
Resource<?> result = null;
try {
result = decodeJob.decodeResultFromCache();//从结果缓存中获取,执行的类是decodeJob
} catch (Exception e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Exception decoding result from cache: " + e);
}
}
if (result == null) {
result = decodeJob.decodeSourceFromCache();//从源文件缓存中获取 ,执行的类是decodeJob
}
return result;
}
-》 decodeJob.decodeResultFromCache();
public Resource<Z> decodeResultFromCache() throws Exception {
if (!diskCacheStrategy.cacheResult()) {//是否支持结果缓存
return null;
}
long startTime = LogTime.getLogTime();
Resource<T> transformed = loadFromCache(resultKey);//从缓存中获取
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Decoded transformed from cache", startTime);
}
startTime = LogTime.getLogTime();
Resource<Z> result = transcode(transformed);//然后执行数据转换
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Transcoded transformed from cache", startTime);
}
return result;
}
-》 decodeJob.loadFromCache(resultKey);//从缓存中获取 一会还会用到,不在重复分析
private Resource<T> loadFromCache(Key key) throws IOException {
File cacheFile = diskCacheProvider.getDiskCache().get(key);//直接从缓存管理中获取
if (cacheFile == null) {
return null;
}
Resource<T> result = null;
try {
result = loadProvider.getCacheDecoder().decode(cacheFile, width, height);//获取到之后,解码
} finally {
if (result == null) {
diskCacheProvider.getDiskCache().delete(key);
}
}
return result;//返回
}
-》 Resource<Z> result =decodeJob. transcode(transformed);//然后执行数据转换
private Resource<Z> transcode(Resource<T> transformed) {
if (transformed == null) {
return null;
}
return transcoder.transcode(transformed);//从一种数据转化为林一种
}
-》再分析另一条,从源文件换种中获取 decodeJob.decodeSourceFromCache();,执行的方法类似,只是,再去除源文件之后,要执行 Resource<T> transformed = transform(decoded);数据变换
-》现在分析,从数据获取EngineRunnable.decodeFromSource();
private Resource<?> decodeFromSource() throws Exception {
return decodeJob.decodeFromSource();
}
->decodeJob.decodeFromSource();
public Resource<Z> decodeFromSource() throws Exception {
Resource<T> decoded = decodeSource();//从数据源加载数据
return transformEncodeAndTranscode(decoded);//变换数据,转化数据
}
-》decodeJob.decodeSource();//从数据源加载数据
private Resource<T> decodeSource() throws Exception {
Resource<T> decoded = null;
try {
long startTime = LogTime.getLogTime();
final A data = fetcher.loadData(priority);//从fetcher加载数据
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Fetched data", startTime);
}
if (isCancelled) {
return null;
}
decoded = decodeFromSourceData(data);//然后解码
} finally {
fetcher.cleanup();
}
return decoded;
}
-》decodeJob.decodeFromSourceData(data);
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;
}
-》再返回到,转换 transformEncodeAndTranscode(decoded);//变换数据,转化数据
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;
}
-》Resource<T> transformed = transform(decoded);
transform(Resource<T> decoded) {
if (decoded == null) {
return null;
}
Resource<T> transformed = transformation.transform(decoded, width, height);
if (!decoded.equals(transformed)) {
decoded.recycle();
}
return transformed;
}
//具体的缓存获取,和回调,需要用时序图分析
问题、
1.Glide中的RequestManager中的请求会不会积压很多,再页面关闭的收再释放?
答:不会,Glide 的所有的请求都在RequestTracker 中,再当前活动,生命周期,关闭的时候,会清空所有的请求缓存,同时对于有View重用的地方,比如ListView,和RecycView
会再当前View被重用的时候,把上一次再本View上的请求,从RequestTracker 中移除,实现方式是通过把请求设置为当前View的tag,通过ViewTarget获取Tag,所以对于
再RecycView中进行大批量的请求,不会导致请求过多不能回收
Glide再RecycView中使用的时候,因为有条目重用的存在,Glide是如何保证图片不出现错乱的?
答:通过为View,设置一个Tag,Tag就是当前的Request,然后再这个View重用的时候,会获取这个View的Tag,如果存在,就是取消前一个请求,并且循环他,处理非常好,值得借鉴
避免了无用的请求。
感觉Glide框架中,那些模块思路设计很好
1.类的功能单一,单一职责原则,让我大开眼界,感觉各个功能拆分的非常好,然后结合工厂设计模式,以类型为区分这些实现,
2.监听View的绘制之前的监听,然后再开始数据的加载,保证了再变换数据,设置数据的时候,View的宽高是有效的
3.RequestManager的设计,再每个活动中,添加Fragment,然后使用这个Fragment感知活动的生命周期,然后,做停止请求,刷新请求,然后可以集中管理这些请求(感知生命
周期,不需要使用者去担心内存泄漏,去取消请求)
4.文件缓存,内存缓存,activiyBitmap(活动的Bitmap)具体意义再哪里还不太清楚,猜测是,这个缓存是缓存正在使用的view,是弱引用,可以更好感知内存,回收资源
5.BitmapPool的设计,很厉害,对于占用内存大小相同的Bitmap,可以重复使用他们,避免频繁的分配整块的内存(会引起频繁的gc,因为Bitmap需要的连续内存空间比较大),提高
流畅度。
6.扩展性非常好,因为功能拆分的很细,然后都是使用工厂模式创建,我们都可以注册使用的工厂,然后实现,可以覆盖,下载,解码,转换,变换,动画,等等功能