1.Glide.with() public static RequestManager with(FragmentActivity activity) { RequestManagerRetriever retriever = RequestManagerRetriever.get(); return retriever.get(activity); } public RequestManager get(FragmentActivity activity) { if (Util.isOnBackgroundThread()) { return get(activity.getApplicationContext()); } else { assertNotDestroyed(activity); FragmentManager fm = activity.getSupportFragmentManager(); return supportFragmentGet(activity, fm); } } RequestManager supportFragmentGet(Context context, FragmentManager fm) { SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm); RequestManager requestManager = current.getRequestManager(); if (requestManager == null) { requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode()); current.setRequestManager(requestManager); } return requestManager; } getSupportRequestManagerFragment这个方法干了啥?就是去创建一个Fragment,把这个创建的Fragment绑定到Activity,就是为了监听activity的生命周期,比如RecyclyerView一个列表 在加载图片,这个时候退出当前Activity应该停止访问网络加载图片,绑定生命周期就有这个好处。 SupportRequestManagerFragment getSupportRequestManagerFragment(final FragmentManager fm) { SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG); if (current == null) { current = pendingSupportRequestManagerFragments.get(fm); if (current == null) { // 创建一个 Fragment 绑定到 Activity 上面 current = new SupportRequestManagerFragment(); pendingSupportRequestManagerFragments.put(fm, current); fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss(); handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget(); } } return current; } //生命周期 RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode, RequestTracker requestTracker, ConnectivityMonitorFactory factory) { this.context = context.getApplicationContext(); this.lifecycle = lifecycle; this.treeNode = treeNode; this.requestTracker = requestTracker; this.glide = Glide.get(context); this.optionsApplier = new OptionsApplier(); ConnectivityMonitor connectivityMonitor = factory.build(context, new RequestManagerConnectivityListener(requestTracker)); // If we're the application level request manager, we may be created on a background thread. In that case we // cannot risk synchronously pausing or resuming requests, so we hack around the issue by delaying adding // ourselves as a lifecycle listener by posting to the main thread. This should be entirely safe. if (Util.isOnBackgroundThread()) { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { lifecycle.addListener(RequestManager.this); } }); } else { lifecycle.addListener(this); } lifecycle.addListener(connectivityMonitor); } LifecycleListener 是个接口有三个方法,onStart() , onStop(),onDestroy() 对应 RequestManager 中的实现分别是: /** * Lifecycle callback that registers for connectivity events (if the android.permission.ACCESS_NETWORK_STATE * permission is present) and restarts failed or paused requests. */ @Override public void onStart() { // onStart might not be called because this object may be created after the fragment/activity's onStart method. resumeRequests(); } /** * Lifecycle callback that unregisters for connectivity events (if the android.permission.ACCESS_NETWORK_STATE * permission is present) and pauses in progress loads. */ @Override public void onStop() { pauseRequests(); } /** * Lifecycle callback that cancels all in progress requests and clears and recycles resources for all completed * requests. */ @Override public void onDestroy() { requestTracker.clearRequests(); } 所以总结一下Glide.with() 这方法返回的是一个 RequestManager 主要用来监听一些生命周期,以此来管理加载请求 Request 。拿 FragmentActivity 来说当 Activity 退出了会调用 onDestroy() -> requestTracker.clearRequests(); 会清理所有的图片加载请求,并且一个 FragmentActivity 只有一个 SupportRequestManagerFragment 和一个 RequestManager 。 2.Glide.with().load() public DrawableTypeRequest<String> load(String string) { return (DrawableTypeRequest<String>) fromString().load(string); } public DrawableTypeRequest<String> fromString() { return loadGeneric(String.class); } private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) { ModelLoader<T, InputStream> streamModelLoader = Glide.buildStreamModelLoader(modelClass, context); ModelLoader<T, ParcelFileDescriptor> 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<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context, glide, requestTracker, lifecycle, optionsApplier)); } Glide.buildStreamModelLoader 和 Glide.buildFileDescriptorModelLoader 这两个方法看不太懂先放一边,待会再回来找他,先记住他的变量名 streamModelLoader 和 fileDescriptorModelLoader,接下来创建了一个 DrawableTypeRequest 返回。 3.Glide.with().load().into() public Target<TranscodeType> into(ImageView view) { Util.assertMainThread(); if (view == null) { throw new IllegalArgumentException("You must pass in a non null View"); } return into(glide.buildImageViewTarget(view, transcodeClass)); } buildTarget返回的是GlideDrawableImageViewTarget,transcodeClass是GlideDrawabe.class,在第2步load的时候赋值。 public <Z> Target<Z> buildTarget(ImageView view, Class<Z> clazz) { if (GlideDrawable.class.isAssignableFrom(clazz)) { return (Target<Z>) new GlideDrawableImageViewTarget(view); } else if (Bitmap.class.equals(clazz)) { return (Target<Z>) new BitmapImageViewTarget(view); } else if (Drawable.class.isAssignableFrom(clazz)) { return (Target<Z>) new DrawableImageViewTarget(view); } else { throw new IllegalArgumentException("Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)"); } } 通过Target构建了一个Request,最后调用 requestTracker.runRequest(request); public <Y extends Target<TranscodeType>> Y into(Y target) { Util.assertMainThread(); // 通过 target 构建一个 Request Request request = buildRequest(target); target.setRequest(request); lifecycle.addListener(target); // 看样子要执行 requestTracker.runRequest(request); return target; } 接下来肯定要分析一下怎么构建 buildRequest的: private Request buildRequest(Target<TranscodeType> target) { if (priority == null) { priority = Priority.NORMAL; } return buildRequestRecursive(target, null); } // 这里省略了一个处理缩略图的方法,感兴趣可以自己研究一下 // obtainRequest private Request obtainRequest(Target<TranscodeType> target, float sizeMultiplier, Priority priority, RequestCoordinator requestCoordinator) { // 构建了一个 GenericRequest 参数很多,但我肯定都知道是啥意思 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); } buildRequest 构建的是一个 GenericRequest 实例,传递的参数很多但是我们肯定都认识,比如 placeholderId,errorId,transformation,diskCacheStrategy 等等,接下来看下真正的 runRequest() 方法: requests.add(request); if (!isPaused) { request.begin(); } else { pendingRequests.add(request); } } @Override public void begin() { startTime = LogTime.getLogTime(); if (model == null) { // 异常报错显示错误图片 onException(null); return; }Draw 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)); } } 然后,调用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; 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.load() 方法: 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()); //处理缓存 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); //one DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation, transcoder, diskCacheProvider, diskCacheStrategy, priority); //two EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority); jobs.put(key, engineJob); engineJob.addCallback(cb); //three 开启线程 engineJob.start(runnable); if (Log.isLoggable(TAG, Log.VERBOSE)) { logWithTimeAndKey("Started new load", startTime, key); } return new LoadStatus(cb, engineJob); } 我们看看EngineRunnable的run 方法: 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); } } 先来看看EngineRunnable. decode方法: private Resource<?> decode() throws Exception { // 判断缓存 if (isDecodingFromCache()) { return decodeFromCache(); } else { return decodeFromSource(); } } 最终调用的是 decodeJob.decodeFromSource() 方法,decodeFromSource()方法,其实它的工作分为两部,第一步是调用decodeSource()方法来获得一个Resource对象,第二步是调用transformEncodeAndTranscode()方法来处理这个Resource对象。 public Resource<Z> decodeFromSource() throws Exception { Resource<T> decoded = decodeSource(); return 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; } 在 decodeSource() 方法中调用了 fetcher.loadData(priority) 和decodeFromSourceData(data); 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; } loadData() 方法如下,主要获取网络输入流。 @Override public ImageVideoWrapper loadData(Priority priority) throws Exception { InputStream is = null; if (streamFetcher != null) { try { is = streamFetcher.loadData(priority); } catch (Exception e) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Exception fetching input stream, trying ParcelFileDescriptor", e); } if (fileDescriptorFetcher == null) { throw e; } } } ParcelFileDescriptor fileDescriptor = null; if (fileDescriptorFetcher != null) { try { fileDescriptor = fileDescriptorFetcher.loadData(priority); } catch (Exception e) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Exception fetching ParcelFileDescriptor", e); } if (is == null) { throw e; } } } return new ImageVideoWrapper(is, fileDescriptor); } 接着回到上面去看下 decodeFromSourceData 这个方法: private Resource<T> decodeFromSourceData(A data) throws IOException { final Resource<T> decoded; if (diskCacheStrategy.cacheSource()) { decoded = cacheAndDecodeSourceData(data); } else { long startTime = LogTime.getLogTime(); //one decoded = loadProvider.getSourceDecoder().decode(data, width, height); if (Log.isLoggable(TAG, Log.VERBOSE)) { logWithTimeAndKey("Decoded from source", startTime); } } return decoded; } loadProvider 就是刚才在 onSizeReady() 方法中得到的FixedLoadProvider,而 getSourceDecoder() 得到的则是一个 GifBitmapWrapperResourceDecoder 对象,也就是要调用这个对象的 decode() 方法来对图片进行解码。 那么我们来看下 GifBitmapWrapperResourceDecoder 的代码: @Override public Resource<GifBitmapWrapper> decode(ImageVideoWrapper source, int width, int height) throws IOException { ByteArrayPool pool = ByteArrayPool.get(); byte[] tempBytes = pool.getBytes(); GifBitmapWrapper wrapper = null; try { wrapper = decode(source, width, height, tempBytes); } finally { pool.releaseBytes(tempBytes); } return wrapper != null ? new GifBitmapWrapperResource(wrapper) : null; } private GifBitmapWrapper decode(ImageVideoWrapper source, int width, int height, byte[] bytes) throws IOException { final GifBitmapWrapper result; if (source.getStream() != null) { result = decodeStream(source, width, height, bytes); } else { result = decodeBitmapWrapper(source, width, height); } return result; } private GifBitmapWrapper decodeStream(ImageVideoWrapper source, int width, int height, byte[] bytes) throws IOException { InputStream bis = streamFactory.build(source.getStream(), bytes); bis.mark(MARK_LIMIT_BYTES); ImageHeaderParser.ImageType type = parser.parse(bis); bis.reset(); GifBitmapWrapper result = null; //one if (type == ImageHeaderParser.ImageType.GIF) { result = decodeGifWrapper(bis, width, height); } // Decoding the gif may fail even if the type matches. if (result == null) { // We can only reset the buffered InputStream, so to start from the beginning of the stream, we need to // pass in a new source containing the buffered stream rather than the original stream. ImageVideoWrapper forBitmapDecoder = new ImageVideoWrapper(bis, source.getFileDescriptor()); result = decodeBitmapWrapper(forBitmapDecoder, width, height); } return result; } private GifBitmapWrapper decodeBitmapWrapper(ImageVideoWrapper toDecode, int width, int height) throws IOException { GifBitmapWrapper result = null; Resource<Bitmap> bitmapResource = bitmapDecoder.decode(toDecode, width, height); if (bitmapResource != null) { result = new GifBitmapWrapper(bitmapResource, null); } return result; } decodeStream 会判断是不是 Gif , 如果不是 Gif 会调用 decodeBitmapWrapper 方法,这个时候会调用 bitmapDecoder.decode() 方法,这个方法应该要去处理图片了? 真正解析Bitmap: @Override public Resource<Bitmap> decode(InputStream source, int width, int height) { Bitmap bitmap = downsampler.decode(source, bitmapPool, width, height, decodeFormat); return BitmapResource.obtain(bitmap, bitmapPool); } public Bitmap decode(InputStream is, BitmapPool pool, int outWidth, int outHeight, DecodeFormat decodeFormat) { final ByteArrayPool byteArrayPool = ByteArrayPool.get(); final byte[] bytesForOptions = byteArrayPool.getBytes(); final byte[] bytesForStream = byteArrayPool.getBytes(); final BitmapFactory.Options options = getDefaultOptions(); // Use to fix the mark limit to avoid allocating buffers that fit entire images. RecyclableBufferedInputStream bufferedStream = new RecyclableBufferedInputStream( is, bytesForStream); // Use to retrieve exceptions thrown while reading. // TODO(#126): when the framework no longer returns partially decoded Bitmaps or provides a way to determine // if a Bitmap is partially decoded, consider removing. ExceptionCatchingInputStream exceptionStream = ExceptionCatchingInputStream.obtain(bufferedStream); // Use to read data. // Ensures that we can always reset after reading an image header so that we can still attempt to decode the // full image even when the header decode fails and/or overflows our read buffer. See #283. MarkEnforcingInputStream invalidatingStream = new MarkEnforcingInputStream(exceptionStream); try { exceptionStream.mark(MARK_POSITION); int orientation = 0; try { orientation = new ImageHeaderParser(exceptionStream).getOrientation(); } catch (IOException e) { if (Log.isLoggable(TAG, Log.WARN)) { Log.w(TAG, "Cannot determine the image orientation from header", e); } } finally { try { exceptionStream.reset(); } catch (IOException e) { if (Log.isLoggable(TAG, Log.WARN)) { Log.w(TAG, "Cannot reset the input stream", e); } } } options.inTempStorage = bytesForOptions; final int[] inDimens = getDimensions(invalidatingStream, bufferedStream, options); final int inWidth = inDimens[0]; final int inHeight = inDimens[1]; final int degreesToRotate = TransformationUtils.getExifOrientationDegrees(orientation); final int sampleSize = getRoundedSampleSize(degreesToRotate, inWidth, inHeight, outWidth, outHeight); final Bitmap downsampled = downsampleWithSize(invalidatingStream, bufferedStream, options, pool, inWidth, inHeight, sampleSize, decodeFormat); // BitmapFactory swallows exceptions during decodes and in some cases when inBitmap is non null, may catch // and log a stack trace but still return a non null bitmap. To avoid displaying partially decoded bitmaps, // we catch exceptions reading from the stream in our ExceptionCatchingInputStream and throw them here. final Exception streamException = exceptionStream.getException(); if (streamException != null) { throw new RuntimeException(streamException); } Bitmap rotated = null; if (downsampled != null) { rotated = TransformationUtils.rotateImageExif(downsampled, pool, orientation); if (!downsampled.equals(rotated) && !pool.put(downsampled)) { downsampled.recycle(); } } return rotated; } finally { byteArrayPool.releaseBytes(bytesForOptions); byteArrayPool.releaseBytes(bytesForStream); exceptionStream.release(); releaseOptions(options); } } 就是从 InputStream 中去获取 Bitmap 对象,这些代码还是比较容易看懂的,Downsampler.decode() 返回的是一个 Bitmap 对象,StreamBitmapDecoder.decode() 对 Bitmap 又进行了一层包裹,返回的是 BitmapResource 。接下来我们回到 GifBitmapWrapperResourceDecoder.decode 中返回的是 GifBitmapWrapperResource , 接着往回走就回到了 DecodeJob.transformEncodeAndTranscode() 中: 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; } private Resource<T> 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; } private Resource<Z> transcode(Resource<T> transformed) { if (transformed == null) { return null; } return transcoder.transcode(transformed); } 上面主要分为三步,transform(),writeTransformedToCache() 写入缓存,transcode() 这里要注意了是把 泛型 T 转成了 Z 。transcode() 方法中又是调用了 transcoder 的 transcode() 方法,发现又找不到代码了,所以我们有得回去找 transcoder 实现类,这也是说我们为什么最好要会画 UML 图,因为代码架构复杂的情况下,我们在里面游几天都上不来。还是回去找找,是在第二步 load 的时候创建的 glide.buildTranscoder(resourceClass, transcodedClass) 是 GifBitmapWrapperDrawableTranscoder : @SuppressWarnings("unchecked") @Override public Resource<GlideDrawable> transcode(Resource<GifBitmapWrapper> toTranscode) { GifBitmapWrapper gifBitmap = toTranscode.get(); Resource<Bitmap> bitmapResource = gifBitmap.getBitmapResource(); final Resource<? extends GlideDrawable> result; if (bitmapResource != null) { result = bitmapDrawableResourceTranscoder.transcode(bitmapResource); } else { result = gifBitmap.getGifResource(); } // This is unchecked but always safe, anything that extends a Drawable can be safely cast to a Drawable. return (Resource<GlideDrawable>) result; } @Override public Resource<GlideBitmapDrawable> transcode(Resource<Bitmap> toTranscode) { GlideBitmapDrawable drawable = new GlideBitmapDrawable(resources, toTranscode.get()); return new GlideBitmapDrawableResource(drawable, bitmapPool); } 这里主要是把 GifBitmapWrapper 转成了 GlideDrawable ,为什么这么弄肯定是为了后面方便显示,因为 Gif 资源返回的已经是 GifDrawable 了并不需要转换,而图片资源返回的是 Bitmap ,做一次转换之后统一转成 GlideBitmapDrawable 这样方便后面做显示。 最后就是回到onLoadComplete中,显示图片,简单说一下, 最终调用了 target 的 onResourceReady() 方法,那么 target 又是谁呢?不知道我们是否还记得这代码into(glide.buildImageViewTarget(view, transcodeClass)) 在之前就分析过的 GlideDrawableImageViewTarget : @Override public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) { if (!resource.isAnimated()) { //TODO: Try to generalize this to other sizes/shapes. // This is a dirty hack that tries to make loading square thumbnails and then square full images less costly // by forcing both the smaller thumb and the larger version to have exactly the same intrinsic dimensions. // If a drawable is replaced in an ImageView by another drawable with different intrinsic dimensions, // the ImageView requests a layout. Scrolling rapidly while replacing thumbs with larger images triggers // lots of these calls and causes significant amounts of jank. float viewRatio = view.getWidth() / (float) view.getHeight(); float drawableRatio = resource.getIntrinsicWidth() / (float) resource.getIntrinsicHeight(); if (Math.abs(viewRatio - 1f) <= SQUARE_RATIO_MARGIN && Math.abs(drawableRatio - 1f) <= SQUARE_RATIO_MARGIN) { resource = new SquaringDrawable(resource, view.getWidth()); } } super.onResourceReady(resource, animation); this.resource = resource; resource.setLoopCount(maxLoopCount); resource.start(); } @Override public void onResourceReady(Z resource, GlideAnimation<? super Z> glideAnimation) { if (glideAnimation == null || !glideAnimation.animate(resource, this)) { setResource(resource); } } @Override protected void setResource(GlideDrawable resource) { view.setImageDrawable(resource); } 现在我们来总结一下 decode() 方法都干了啥,首先是 DecodeJob.decodeFromSource() -> fetcher.loadData() 去联网获取 InputStream -> loadProvider.getSourceDecoder().decode() -> bitmapDecoder.decode() 解析 InputStream 压缩旋转等等返回 Bitmap -> DecodeJob.transformEncodeAndTranscode() 去转换保证返回数据一致 GlideDrawable 。 最后一步,接下来只需要看下 onLoadComplete , 最终调用了 target 的 onResourceReady() 方法,那么 target 又是谁呢?不知道我们是否还记得这代码into(glide.buildImageViewTarget(view, transcodeClass)) 在之前就分析过的 GlideDrawableImageViewTarget : @Override protected void setResource(GlideDrawable resource) { view.setImageDrawable(resource); }
Glide源码流程分析
最新推荐文章于 2019-08-06 20:01:39 发布