android其实很简单 -- Glide简单分析
16lz
2021-01-26
最近在使用Glide,遇到不少不解的问题
- 生命周期是如何绑定的
- 缓存策略
从官方的例子开始
// 这里的this我们假设为Activity Glide.with(this).load("http://goo.gl/gEgYUd").into(imageView);
with
// with返回了一个RequestManager,RequestManager将acitivity生命周期与request绑定 // https://github.com/bumptech/glide/blob/3.0/library/src/main/java/com/bumptech/glide/Glide.java#L668 public static RequestManager with(Activity activity) { RequestManagerRetriever retriever = RequestManagerRetriever.get(); return retriever.get(activity); } // https://github.com/bumptech/glide/blob/3.0/library/src/main/java/com/bumptech/glide/manager/RequestManagerRetriever.java#L120 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); } } // https://github.com/bumptech/glide/blob/3.0/library/src/main/java/com/bumptech/glide/manager/RequestManagerRetriever.java#L167 @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.getGlideLifecycle(), current.getRequestManagerTreeNode()); current.setRequestManager(requestManager); } return requestManager; } // https://github.com/bumptech/glide/blob/3.0/library/src/main/java/com/bumptech/glide/manager/RequestManagerRetriever.java#L152 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm) { RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG); if (current == null) { current = pendingRequestManagerFragments.get(fm); if (current == null) { // 这里生成了一个Fragment,通过重载其生命周期回调,就可以绑定activity的生命周期 current = new RequestManagerFragment(); pendingRequestManagerFragments.put(fm, current); fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss(); handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget(); } } return current; } // https://github.com/bumptech/glide/blob/3.0/library/src/main/java/com/bumptech/glide/manager/RequestManagerFragment.java @Override public void onStart() { super.onStart(); lifecycle.onStart(); } @Override public void onStop() { super.onStop(); lifecycle.onStop(); } @Override public void onDestroy() { super.onDestroy(); lifecycle.onDestroy(); }
load
// 开始加载图片啦,首先生成了一个DrawableTypeRequest // https://github.com/bumptech/glide/blob/3.0/library/src/main/java/com/bumptech/glide/RequestManager.java#L283 public DrawableTypeRequest load(String string) { return (DrawableTypeRequest) fromString().load(string); } // https://github.com/bumptech/glide/blob/3.0/library/src/main/java/com/bumptech/glide/RequestManager.java#L303 public DrawableTypeRequest fromString() { return loadGeneric(String.class); } // https://github.com/bumptech/glide/blob/3.0/library/src/main/java/com/bumptech/glide/RequestManager.java#L624 private DrawableTypeRequest loadGeneric(Class modelClass) { ModelLoader streamModelLoader = Glide.buildStreamModelLoader(modelClass, context); ModelLoader fileDescriptorModelLoader = Glide.buildFileDescriptorModelLoader(modelClass, context); if (modelClass != null && streamModelLoader == null && fileDescriptorModelLoader == null) { throw new IllegalArgumentException("Unknown type " + modelClass + ". You must provide a Model of a type for" + " which there is a registered ModelLoader, if you are using a custom model, you must first call" + " Glide#register with a ModelLoaderFactory for your custom model class"); } return optionsApplier.apply( new DrawableTypeRequest(modelClass, streamModelLoader, fileDescriptorModelLoader, context, glide, requestTracker, lifecycle, optionsApplier)); } // https://github.com/bumptech/glide/blob/3.0/library/src/main/java/com/bumptech/glide/DrawableTypeRequest.java#L30 // DrawableTypeRequest继承自DrawableRequestBuilder,通过optionsApplier.apply可以调整加载参数 public class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<ModelType> implements DownloadOptions {...}
into
// https://github.com/bumptech/glide/blob/3.0/library/src/main/java/com/bumptech/glide/DrawableRequestBuilder.java#L456 // into正式开始加载图片,包括下载缓存显示 @Override public Target into(ImageView view) { return super.into(view); } // https://github.com/bumptech/glide/blob/3.0/library/src/main/java/com/bumptech/glide/GenericRequestBuilder.java#L682 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. } } // 这里buildImageViewTarget返回了ImageViewTarget(确切来说是子类),封装了一个ImageView,在request结束后会设置对应的image return into(glide.buildImageViewTarget(view, transcodeClass)); } // https://github.com/bumptech/glide/blob/3.0/library/src/main/java/com/bumptech/glide/GenericRequestBuilder.java#L648 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(); } // 这里的buildRequest最后会返回一个GenericRequest // (代码很长,通过窥屏知道的http://blog.csdn.net/guolin_blog/article/details/53939176/) Request request = buildRequest(target); target.setRequest(request); lifecycle.addListener(target); requestTracker.runRequest(request); return target; } // https://github.com/bumptech/glide/blob/3.0/library/src/main/java/com/bumptech/glide/manager/RequestTracker.java#L34 public void runRequest(Request request) { requests.add(request); if (!isPaused) { // 请求从这里开始发起,搜索内存,磁盘缓存,及网络请求 request.begin(); } else { pendingRequests.add(request); } } // https://github.com/bumptech/glide/blob/3.0/library/src/main/java/com/bumptech/glide/request/GenericRequest.java#L261 @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)); } } // https://github.com/bumptech/glide/blob/3.0/library/src/main/java/com/bumptech/glide/request/GenericRequest.java#L425 @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; // 这里进入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)); } } // https://github.com/bumptech/glide/blob/3.0/library/src/main/java/com/bumptech/glide/load/engine/Engine.java // 简单看下,主要是查缓存及网络请求了 public LoadStatus load(Key signature, int width, int height, DataFetcher fetcher, DataLoadProvider loadProvider, Transformation transformation, ResourceTranscoder 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()); 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; } 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; } 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); } EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable); DecodeJob decodeJob = new DecodeJob(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); if (Log.isLoggable(TAG, Log.VERBOSE)) { logWithTimeAndKey("Started new load", startTime, key); } return new LoadStatus(cb, engineJob); }
更多相关文章
- IntentService源码分析
- 阿里Android(安卓)26条规范经验及优化
- Android中存储目录
- Android网络通信库Volley简介
- 第五章 网络 之 Android网络知识&框架
- android开发,加载网络图片时 报错android.os.NetworkOnMainThread
- Android(安卓)Volley框架详解
- Android使用glide加载gif动画设置播放次数
- urlConn.setRequestProperty是做什么的以及作用