内容简介:先来说下世面上常用的三种图片加载框架Picasso,Glide,FrescoPicasso与Glide相比:Fresco
先来说下世面上常用的三种图片加载框架Picasso,Glide,Fresco
Picasso与Glide相比:
- 相似——api上的调用差不多,都支持内存缓存,glide是picasso的升级,性能有一定的提升
- 差异
- 缓存不同,picasso2级缓存,没有磁盘缓存,Glide三级缓存,内存-磁盘-网络的优先级加载黑乎乎。
- Picasso默认加载的图片格式是ARGB-8888,Glide默认是RGB-565,内存开销节省小一半
- Picasso是加载全尺寸图片到内存中,下次在任何imageView中加载图片时,先取全尺寸图片,重新调整大小,再存缓存。而Glide是按ImageView的大小缓存的,为每种大小缓存一次。 Glide这种方式是空间换时间 ,大小几乎是picasso的2倍
- 生命周期问题,Glide的with方法图片加载会和Activity与Fragment的生命周期一致
- Glide可以加载GIF
- Picasso包特别小,100k左右,方法法为850,glide大概500k,2700个方法。
Fresco
- 优点:
- 图片存储在安卓系统匿名共享内存区,而不是虚拟机的堆内存,图片的中间缓冲数据也存放在本地堆内存,所以应用有更多的内存空间使用。不容易OOM,减少GC回收
- 渐近式加载,支持图片从模糊到清晰,用户体验极好
- 图片可以以任意为中心点显示在ImageView
- JPEG图片改变大小也是在native进行,不在虚拟机堆内存,同样减少OOM
- 对GIF支持友好
- 缺点
- 包太大,2-3M
- 用法复杂
- 底层都是C/C++,源码阅读有挑战性
小结
Glide能做Picasso能做的所有事情,更快,能处理大型图片流,一般Glide是首选;Fresco当使用图片非常多的应用时,它的优势非常明显
Glide的基本使用
implementation ("com.github.bumptech.glide:glide:4.9.0") { exclude group: "com.android.support" } annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0' 复制代码
Glide.with(this) .load("http://pic37.nipic.com/20140113/8800276_184927469000_2.png") .into(imageView); <uses-permission android:name="android.permission.INTERNET" /> 复制代码
需要注意的是,我们在Android9.0以上使用,用的http请求的话,需要在AndroidMainfest中
<application ... android:usesCleartextTraffic="true"> 复制代码
原因是android9.0以后,默认禁止http请求的。
Glide源码
Glide.with(实例化Glide并获取RequestManager)
先看Glide.with()方法
@NonNull public static RequestManager with(@NonNull Context context) { return getRetriever(context).get(context); } @NonNull public static RequestManager with(@NonNull Activity activity) { return getRetriever(activity).get(activity); } @NonNull public static RequestManager with(@NonNull FragmentActivity activity) { return getRetriever(activity).get(activity); } @NonNull public static RequestManager with(@NonNull Fragment fragment) { return getRetriever(fragment.getActivity()).get(fragment); } @SuppressWarnings("deprecation") @Deprecated @NonNull public static RequestManager with(@NonNull android.app.Fragment fragment) { return getRetriever(fragment.getActivity()).get(fragment); } @NonNull public static RequestManager with(@NonNull View view) { return getRetriever(view.getContext()).get(view); } 复制代码
可以看到,with方法有多个重载方法,而且都是先调用了 getRetriever
这个方法,那么我们先看这个方法的源码
@NonNull private static RequestManagerRetriever getRetriever(@Nullable Context context) { ... return Glide.get(context).getRequestManagerRetriever(); } 复制代码
从源码看,直接是调用Glide的get()方法,然后再调用 getRequestManagerRetriever
先看get方法
@NonNull public static Glide get(@NonNull Context context) { if (glide == null) { synchronized (Glide.class) { if (glide == null) { checkAndInitializeGlide(context); } } } return glide; } 复制代码
一看原来 Glide是单例,只有第一次会实例化 ,通过Builder模式实例化Glide对象,初始化后调用getRequestManagerRetriever方法来得到RequestManagerRetriever对象。
生命周期管理
那么问题又回到了getRetriever(xxx).get(xxx);这里,当getRetriever得到了RequestManagerRetriever对象,我们继续看后面的get方法
//get方法也和with一样,有多个对应的重载 @NonNull public RequestManager get(@NonNull Context context) { if (context == null) { throw new IllegalArgumentException("You cannot start a load on a null Context"); } else if (Util.isOnMainThread() && !(context instanceof Application)) { //直接返回ApplicationManager 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()); } } //传入的context为ApplicationContext return getApplicationManager(context); } //get(Activity/fragement)逻辑都差不多的,这里只拿getFragmentActivity来讲 @NonNull public RequestManager get(@NonNull FragmentActivity activity) { if (Util.isOnBackgroundThread()) { //后台时,就调用get(context) return get(activity.getApplicationContext()); } else { assertNotDestroyed(activity); //前台可见,创建一个FragmentManager FragmentManager fm = activity.getSupportFragmentManager(); return supportFragmentGet( activity, fm, /*parentHint=*/ null, isActivityVisible(activity)); } } @NonNull private RequestManager supportFragmentGet( @NonNull Context context, @NonNull FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) { //获取RequestManager SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint, isParentVisible); RequestManager requestManager = current.getRequestManager(); if (requestManager == null) { // TODO(b/27524013): Factor out this Glide.get() call. Glide glide = Glide.get(context); //如果得到requestManager为空,创建requestManager,并把Lifecycle传了进去 requestManager = factory.build( glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context); //缓存这个requestManager current.setRequestManager(requestManager); } return requestManager; } //创建并添加一个SupportRequestManagerFragment @NonNull private SupportRequestManagerFragment getSupportRequestManagerFragment( @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) { SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG); if (current == null) { current = pendingSupportRequestManagerFragments.get(fm); if (current == null) { current = new SupportRequestManagerFragment(); current.setParentFragmentHint(parentHint); if (isParentVisible) { current.getGlideLifecycle().onStart(); } pendingSupportRequestManagerFragments.put(fm, current); //在这里,使用fragmentManager添加了一个隐藏的无界面Fragment fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss(); handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget(); } } return current; } 复制代码
可以看到,get方法的重载方法很多,但是核心都是一样的的,就是返回两种requestManager,1. ApplicationManager,它的生命周期与应用同步,应用退出,Glide也退出;2. 附加在Fragment之上的requestManager,通过这个fragment,绑定了对应的生命周期,这样就可以在Activity销毁时往上加载了,RxPermission也是这么设计的。
public class SupportRequestManagerFragment extends Fragment { private static final String TAG = "SupportRMFragment"; private final ActivityFragmentLifecycle lifecycle; ... @Override public void onAttach(Context context) { super.onAttach(context); try { registerFragmentWithRoot(getActivity()); } catch (IllegalStateException e) { // OnAttach can be called after the activity is destroyed, see #497. if (Log.isLoggable(TAG, Log.WARN)) { Log.w(TAG, "Unable to register fragment with root", e); } } } @Override public void onDetach() { super.onDetach(); parentFragmentHint = null; unregisterFragmentWithRoot(); } @Override public void onStart() { super.onStart(); lifecycle.onStart(); } @Override public void onStop() { super.onStop(); lifecycle.onStop(); } @Override public void onDestroy() { super.onDestroy(); lifecycle.onDestroy(); unregisterFragmentWithRoot(); } ... } 复制代码
可以看到,SupportRequestManagerFragment就是这么设计的,注入了一个生命周期监听器ActivityFragmentLifecycle,并在Fragment的各个生命周期中,调用了对应的方法。
class ActivityFragmentLifecycle implements Lifecycle { ... @Override public void addListener(@NonNull LifecycleListener listener) { lifecycleListeners.add(listener); if (isDestroyed) { listener.onDestroy(); } else if (isStarted) { listener.onStart(); } else { listener.onStop(); } } @Override public void removeListener(@NonNull LifecycleListener listener) { lifecycleListeners.remove(listener); } void onStart() { isStarted = true; for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) { lifecycleListener.onStart(); } } void onStop() { isStarted = false; for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) { lifecycleListener.onStop(); } } void onDestroy() { isDestroyed = true; for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) { lifecycleListener.onDestroy(); } } } 复制代码
可以看到,在ActivityFragmentLifecycle会紧接着调用lifecycleListener监听器,而这个监听器其实就是RequestManager。
最后,可以看到,生命周期已与requestManager进行了绑定。
RequestBuilder
load
接下来我们看load方法的源码
public RequestBuilder<Drawable> load(@Nullable String string) { return asDrawable().load(string); } 复制代码
先来看前面的asDrawable
public RequestBuilder<Drawable> asDrawable() { return as(Drawable.class); } public <ResourceType> RequestBuilder<ResourceType> as( @NonNull Class<ResourceType> resourceClass) { return new RequestBuilder<>(glide, this, resourceClass, context); } 复制代码
其实就相当于new RequestBuilder,那再看load
public RequestBuilder<TranscodeType> load(@Nullable String string) { return loadGeneric(string); } @NonNull private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) { this.model = model; isModelSet = true; return this; } 复制代码
可以看到load方法非常简单,其实是创建了RequestBuilder,并把传递进来的参数url赋值给RequestBuilder中。
into方法实现资源加载并设置到target中
再看into方法
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) { Util.assertMainThread(); Preconditions.checkNotNull(view); BaseRequestOptions<?> requestOptions = this; if (!requestOptions.isTransformationSet() && requestOptions.isTransformationAllowed() && view.getScaleType() != null) { // Clone in this method so that if we use this RequestBuilder to load into a View and then // into a different target, we don't retain the transformation applied based on the previous // View's scale type. //这些都与ImageView的scaleType相关,是转换逻辑,与我们关心的代码流程无关,可以不用关心 switch (view.getScaleType()) { case CENTER_CROP: requestOptions = requestOptions.clone().optionalCenterCrop(); break; case CENTER_INSIDE: requestOptions = requestOptions.clone().optionalCenterInside(); break; case FIT_CENTER: case FIT_START: case FIT_END: requestOptions = requestOptions.clone().optionalFitCenter(); break; case FIT_XY: requestOptions = requestOptions.clone().optionalCenterInside(); break; case CENTER: case MATRIX: default: // Do nothing. } } //真正执行的代码在这 return into( glideContext.buildImageViewTarget(view, transcodeClass), /*targetListener=*/ null, requestOptions, Executors.mainThreadExecutor()); } 复制代码
分析源码可以知道,它的内部调用了into的重载方法
我们先看里面的参数方法glideContext.buildImageViewTarget(view, transcodeClass),
@NonNull public <X> ViewTarget<ImageView, X> buildImageViewTarget( @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) { return imageViewTargetFactory.buildTarget(imageView, transcodeClass); } public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view, @NonNull Class<Z> clazz) { if (Bitmap.class.equals(clazz)) { return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view); } else if (Drawable.class.isAssignableFrom(clazz)) { return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view); } else { throw new IllegalArgumentException( "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)"); } } 复制代码
可以看到,返回了ViewTarger,还记得上面我们看到的asDrawable么,说明是DrawableImageViewTarget,接下来再看外层的into方法
private <Y extends Target<TranscodeType>> Y into( @NonNull Y target, @Nullable RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> options, Executor callbackExecutor) { Preconditions.checkNotNull(target); if (!isModelSet) { throw new IllegalArgumentException("You must call #load() before calling #into()"); } //创建request Request request = buildRequest(target, targetListener, options, callbackExecutor); //获取targert之前的请求任务(如果有的话) Request previous = target.getRequest(); if (request.isEquivalentTo(previous) && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) { //新构建的request上一个相等,并且设置了缓存以及没有执行完成 //释放新的request request.recycle(); // If the request is completed, beginning again will ensure the result is re-delivered, // triggering RequestListeners and Targets. If the request is failed, beginning again will // restart the request, giving it another chance to complete. If the request is already // running, we can let it continue running without interruption. if (!Preconditions.checkNotNull(previous).isRunning()) { //当旧的request没有在运行。执行它的begin // Use the previous request rather than the new one to allow for optimizations like skipping // setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions // that are done in the individual Request. previous.begin(); } return target; } // 清除先Target之前的所有任务并释放资源 requestManager.clear(target); //把新的request设置给target target.setRequest(request); //在这里执行request,下载图片任务 requestManager.track(target, request); return target; } private boolean isSkipMemoryCacheWithCompletePreviousRequest( BaseRequestOptions<?> options, Request previous) { //是否设置缓存以及上一次是否执行完成 return !options.isMemoryCacheable() && previous.isComplete(); } 复制代码
这里主要做了两件事:
- 通过buildRequest构建了一个request
- 获取target的上一个request对象,与新的request对比,并检测是否采用了缓存及target的上次请求是否完成
- 两个对象相等,并且options采用了缓存或target上一次没有请求完,则将新的request回收,并判断target的request是否还在运行,没有的话begin,并返回
- 两个对象不相等,或者option没有使用缓存和target请求完成了,清除target的之间设置,并将新的request对象设置给target,通过track方法启动request请求。
再来看requestManager的track方法
synchronized void track(@NonNull Target<?> target, @NonNull Request request) { targetTracker.track(target); requestTracker.runRequest(request); } public void track(@NonNull Target<?> target) { targets.add(target); } public void runRequest(@NonNull Request request) { requests.add(request); if (!isPaused) { //当处于前台可见时,调用request的begin request.begin(); } else { request.clear(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Paused, delaying request"); } //先不执行request,只把它加入到一个准备队列 pendingRequests.add(request); } } 复制代码
可的看到,track方法是先将target添加到targetTracker类的targets集合中,然后运行request的begin方法。
到这里,其实图片加载网络资源的流程已经完成了大半了。接下来接着看如何加载资源并显示到target上的。
Request实现加载资源及显示
我们直接点request.begin方法去跟踪源码,会发现Request只是一个接口,所以我们要找到它的实现类。
那么我们再看上面的创建request方法
private Request buildRequest( Target<TranscodeType> target, @Nullable RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> requestOptions, Executor callbackExecutor) { return buildRequestRecursive( target, targetListener, /*parentCoordinator=*/ null, transitionOptions, requestOptions.getPriority(), requestOptions.getOverrideWidth(), requestOptions.getOverrideHeight(), requestOptions, callbackExecutor); } //参数是真鸡儿长 private Request buildRequestRecursive( Target<TranscodeType> target, @Nullable RequestListener<TranscodeType> targetListener, @Nullable RequestCoordinator parentCoordinator, TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority, int overrideWidth, int overrideHeight, BaseRequestOptions<?> requestOptions, Executor callbackExecutor) { ... //关键代码 Request mainRequest = buildThumbnailRequestRecursive( target, targetListener, parentCoordinator, transitionOptions, priority, overrideWidth, overrideHeight, requestOptions, callbackExecutor); if (errorRequestCoordinator == null) { return mainRequest; } ... //如果有设置错误时的处理逻辑 return errorRequestCoordinator; } 复制代码
可以看到,真正的核心代码在buildThumbnailRequestRecursive方法
//这个方法结构其实很简单,但是参数太多,所以把参数省略再看 private Request buildThumbnailRequestRecursive( ...) { //默认的thumbnailBuilder就是空的,除非手动调用RequestBuilder类的thumbnail方法 //否则这个if代码块永远执行不到 if (thumbnailBuilder != null) { // Recursive case: contains a potentially recursive thumbnail request builder. 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()"); } TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions = thumbnailBuilder.transitionOptions; // Apply our transition by default to thumbnail requests but avoid overriding custom options // that may have been applied on the thumbnail request explicitly. if (thumbnailBuilder.isDefaultTransitionOptionsSet) { thumbTransitionOptions = transitionOptions; } //缩略图权限 Priority thumbPriority = thumbnailBuilder.isPrioritySet() ? thumbnailBuilder.getPriority() : getThumbnailPriority(priority); //缩略图宽高 int thumbOverrideWidth = thumbnailBuilder.getOverrideWidth(); int thumbOverrideHeight = thumbnailBuilder.getOverrideHeight(); //宽高检验 if (Util.isValidDimensions(overrideWidth, overrideHeight) && !thumbnailBuilder.isValidOverride()) { thumbOverrideWidth = requestOptions.getOverrideWidth(); thumbOverrideHeight = requestOptions.getOverrideHeight(); } //缩略图请求协议器,同时协调原图与缩略图的request ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator); //原图请求 Request fullRequest = obtainRequest(...); isThumbnailBuilt = true; // Recursively generate thumbnail requests. //调用buildRequestRecursive,还是会调到buildThumbnailRequestRecursive,这是个递归方法 //递归生成缩略图请求 Request thumbRequest = thumbnailBuilder.buildRequestRecursive(...); isThumbnailBuilt = false; //把这两个request包装到ThumbnailRequestCoordinator中 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(...); BaseRequestOptions<?> thumbnailOptions = requestOptions.clone().sizeMultiplier(thumbSizeMultiplier); Request thumbnailRequest = obtainRequest(...); coordinator.setRequests(fullRequest, thumbnailRequest); return coordinator; } else { //只加载原图 // Base case: no thumbnail. return obtainRequest(...); } } 复制代码
可以看到,在buildThumbnailRequestRecursive主要做了有无缩略图的判断,然后再进行加载,最后调用了obtainRequest方法
private Request obtainRequest( Target<TranscodeType> target, RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> requestOptions, RequestCoordinator requestCoordinator, TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority, int overrideWidth, int overrideHeight, Executor callbackExecutor) { return SingleRequest.obtain( context, glideContext, model,//对应load(url),比如一个图片地址 transcodeClass, requestOptions, overrideWidth,//宽 overrideHeight,//高 priority, target, targetListener, requestListeners, requestCoordinator, glideContext.getEngine(),//全局加载引擎 transitionOptions.getTransitionFactory(), callbackExecutor); } 复制代码
这个方法通过 SingleReques
类的方法obtain去创建一个Request对象,所以,它就是我们要找的requst,那么看它的begin方法
开启资源加载任务
@Override public synchronized void begin() { assertNotCallingCallbacks(); stateVerifier.throwIfRecycled(); startTime = LogTime.getLogTime(); //如果图片的来源没有设置,加载失败 if (model == null) { if (Util.isValidDimensions(overrideWidth, overrideHeight)) { width = overrideWidth; height = overrideHeight; } // Only log at more verbose log levels if the user has set a fallback drawable, because // fallback Drawables indicate the user expects null models occasionally. int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG; onLoadFailed(new GlideException("Received null model"), logLevel); return; } if (status == Status.RUNNING) { throw new IllegalArgumentException("Cannot restart a running request"); } // If we're restarted after we're complete (usually via something like a notifyDataSetChanged // that starts an identical request into the same Target or View), we can simply use the // resource and size we retrieved the last time around and skip obtaining a new size, starting a // new load etc. This does mean that users who want to restart a load because they expect that // the view size has changed will need to explicitly clear the View or Target before starting // the new load. if (status == Status.COMPLETE) { onResourceReady(resource, DataSource.MEMORY_CACHE); return; } // Restarts for requests that are neither complete nor running can be treated as new requests // and can run again from the beginning. status = Status.WAITING_FOR_SIZE; //如果Target的宽高已经获取并合法,就开始下一步 if (Util.isValidDimensions(overrideWidth, overrideHeight)) { onSizeReady(overrideWidth, overrideHeight); } else { //手动获取宽高 target.getSize(this); } if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE) && canNotifyStatusChanged()) { //设置占位图 target.onLoadStarted(getPlaceholderDrawable()); } if (IS_VERBOSE_LOGGABLE) { logV("finished run method in " + LogTime.getElapsedMillis(startTime)); } } 复制代码
可以看到,begin方法经过一系列的判断,当status是RUNNING或者WAITING_FOR_SIZE状态,并且需要设置占位图时,会调用onLoadStarted设置占位图,当状态是COMPLETE时,会执行onResourceReady方法并返回。
@Override public synchronized void onResourceReady(Resource<?> resource, DataSource dataSource) { stateVerifier.throwIfRecycled(); loadStatus = null; ... //判断是否需要设置资源,如果不需要就直接释放并设置状态为COMPLETE if (!canSetResource()) { releaseResource(resource); // We can't put the status to complete before asking canSetResource(). status = Status.COMPLETE; return; } //执行方法 onResourceReady((Resource<R>) resource, (R) received, dataSource); } 复制代码
上面省略了一大段加载失败的代码,直接来看onResourceReady的重载方法。
private synchronized void onResourceReady(Resource<R> resource, R result, DataSource dataSource) { // We must call isFirstReadyResource before setting status. boolean isFirstResource = isFirstReadyResource(); status = Status.COMPLETE; this.resource = resource; ... try { boolean anyListenerHandledUpdatingTarget = false; if (requestListeners != null) { for (RequestListener<R> listener : requestListeners) { anyListenerHandledUpdatingTarget |= listener.onResourceReady(result, model, target, dataSource, isFirstResource); } } anyListenerHandledUpdatingTarget |= targetListener != null && targetListener.onResourceReady(result, model, target, dataSource, isFirstResource); //设置资源及动画相关的信息 if (!anyListenerHandledUpdatingTarget) { Transition<? super R> animation = animationFactory.build(dataSource, isFirstResource); //这个target有多个,比如DrawableImageViewTarget target.onResourceReady(result, animation); } } finally { isCallingCallbacks = false; } //最后通知加载成功 notifyLoadSuccess(); } 复制代码
可以看到,当状态为COMPLETE时,就是把当前result设置到当前的target上,并通知加载成功(做一些加载成功后的清理工作)。
上面是COMPLETE时的状态,那么不是这个状态时呢?会执行到onSizeReady方法
@Override public synchronized void onSizeReady(int width, int height) { stateVerifier.throwIfRecycled(); ... status = Status.RUNNING; //计算缩略图的尺寸 float sizeMultiplier = requestOptions.getSizeMultiplier(); this.width = maybeApplySizeMultiplier(width, sizeMultiplier); this.height = maybeApplySizeMultiplier(height, sizeMultiplier); if (IS_VERBOSE_LOGGABLE) { logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime)); } //加载流程 loadStatus = engine.load( glideContext, model,//对应rul,图片地址 requestOptions.getSignature(), this.width, this.height, requestOptions.getResourceClass(),//默认是Object.class transcodeClass,//默认是Drawable.class priority, requestOptions.getDiskCacheStrategy(),//缓存策略,默认是AUTOMATIC requestOptions.getTransformations(), requestOptions.isTransformationRequired(), requestOptions.isScaleOnlyOrNoTransform(), requestOptions.getOptions(), requestOptions.isMemoryCacheable(), requestOptions.getUseUnlimitedSourceGeneratorsPool(), requestOptions.getUseAnimationPool(), requestOptions.getOnlyRetrieveFromCache(), this, callbackExecutor); } 复制代码
可以看到,调用了Engine的load方法,关于加载图片的加载机制,我们下一篇再讲,今天先就讲到这。
总结
这一篇主要分析Glide.with().load().into()的简单流程
- Glide类作为入口类,调用静态方法with(),实例化了Glide这个单例,取得RequestManager对象并返回
- RequestManager去管理Request请求,根据Activity或Fragment生命周期,管理request请求,包括:onStop,onStart,onDestory,pauseRequest,resumeRequests等,并可以设置加载资源要返回的资源类型,Bitmap,Drawable,Gif。通过调用load()、asBitmap()、asFile()等方法均返回一个RquestBuilder对象,将资源的请求处理移交给了RequestBuilder,实现将功能分离,模块化处理。
- RquestBuilder处理资源加载请求,调用apply()方法传入RequestOptions对象进行一些选项设置;调用transition()方法实现资源加载显示时过度动画;最后调用into()方法,去构建Rquest对象或使用Target设置过的Request对象,调用Rquest的对象方法begin()开启加载请求。
- 开启请求后的工作就移交到Request类中,加载完成后,Request调用onResourceReady()方法去判断加载结果,若加载成功,调用Target类的onReadySuccess()方法设置资源,调用RequestCoordinator中方法onRequestSuccess()执行加载成功后的资源清理工作。若加载失败,Request直接调用notifyLoadFailed()方法,将清理资源工作移交给RequestCoordinator类处理。
参考
- Glide最全解析系列文章 - 郭神基于3.x版本的。
- Android图片加载框架Glide源码解析(二)
- 深入理解Glide
- Glide使用简介及流程分析
下面是我的公众号,欢迎大家关注我
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 以太坊源码分析(36)ethdb源码分析
- [源码分析] kubelet源码分析(一)之 NewKubeletCommand
- libmodbus源码分析(3)从机(服务端)功能源码分析
- [源码分析] nfs-client-provisioner源码分析
- [源码分析] kubelet源码分析(三)之 Pod的创建
- Spring事务源码分析专题(一)JdbcTemplate使用及源码分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
C语言程序开发范例宝典
2010-1 / 59.00元
《C语言程序开发范例宝典》全面介绍了应用C语言进行开发的各种技术和技巧,全书共分12章,内容包括基础知识、指针、数据结构、算法、数学应用、文件操作、库函数应用、图形图像、系统调用、加解密与安全性、游戏、综合应用等。全书共提供300个实例,每个实例都突出了其实用性。 《C语言程序开发范例宝典》既可作为C程序的初学者学习用书,也可作为程序开发人员、相关培训机构老师和学生的参考用书。一起来看看 《C语言程序开发范例宝典》 这本书的介绍吧!