文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android源码进阶之Glide加载流程和源码详解

2024-12-14 00:56

关注

前言

Glide是纯Java写的Android端开源图片加载库,能够帮助我们下载、缓存、展示多种格式图片,也包括GIF格式;

昨天我们从源码里分析了,glide的缓存策略机制;

那今天我们就趁热打铁来分析一波加载流程;

一、glide常用的加载方法

1、加载图片到imageView

  1. Glide.with(Context context).load(Strint url).into(ImageView imageView); 

2、各种形式的图片加载到ImageView

  1. // 加载本地图片 
  2. File file = new File(getExternalCacheDir() + "/image.jpg"); 
  3. Glide.with(this).load(file).into(imageView); 
  4. // 加载应用资源 
  5. int resource = R.drawable.image; 
  6. Glide.with(this).load(resource).into(imageView); 
  7. // 加载二进制流 
  8. byte[] image = getImageBytes(); 
  9. Glide.with(this).load(image).into(imageView); 
  10. // 加载Uri对象 
  11. Uri imageUri = getImageUri(); 
  12. Glide.with(this).load(imageUri).into(imageView); 

3、加载带有占位图

  1. Glide.with(this).load(url).placeholder(R.drawable.loading).into(imageView); 

占位图目的为在目的图片还未加载出来的时候,提前展示给用户的一张图片;

4、加载失败 放置占位符

  1. Glide.with(this).load(url).placeholder(R.drawable.loading).error(R.drawable.error) 
  2.      .diskCacheStrategy(DiskCacheStrategy.NONE)//关闭Glide的硬盘缓存机制 
  3.      .into(imageView); 
  4. //DiskCacheStrategy.NONE:表示不缓存任何内容。 
  5. //DiskCacheStrategy.SOURCE:表示只缓存原始图片。 
  6. //DiskCacheStrategy.RESULT:表示只缓存转换过后的图片(默认选项)。 
  7. //DiskCacheStrategy.ALL :表示既缓存原始图片,也缓存转换过后的图片。 

5、加载指定格式的图片--指定为静止图片

  1. Glide.with(this) 
  2.      .load(url) 
  3.      .asBitmap()//只加载静态图片,如果是git图片则只加载第一帧。 
  4.      .placeholder(R.drawable.loading) 
  5.      .error(R.drawable.error) 
  6.      .diskCacheStrategy(DiskCacheStrategy.NONE) 
  7.      .into(imageView); 

6、加载动态图片

  1. Glide.with(this) 
  2.      .load(url) 
  3.      .asGif()//加载动态图片,若现有图片为非gif图片,则直接加载错误占位图。 
  4.      .placeholder(R.drawable.loading) 
  5.      .error(R.drawable.error) 
  6.      .diskCacheStrategy(DiskCacheStrategy.NONE) 
  7.      .into(imageView); 

7、加载指定大小的图片

  1. Glide.with(this) 
  2.      .load(url) 
  3.      .placeholder(R.drawable.loading) 
  4.      .error(R.drawable.error) 
  5.      .diskCacheStrategy(DiskCacheStrategy.NONE) 
  6.      .override(100, 100)//指定图片大小 
  7.      .into(imageView); 

8、关闭框架的内存缓存机制

  1. Glide.with(this) 
  2.      .load(url) 
  3.      .skipMemoryCache(true)  //传入参数为false时,则关闭内存缓存。 
  4.      .into(imageView); 

9、关闭硬盘的缓存

  1. Glide.with(this) 
  2.      .load(url) 
  3.      .diskCacheStrategy(DiskCacheStrategy.NONE)     //关闭硬盘缓存操作 
  4.      .into(imageView); 
  5. //其他参数表示: 
  6. //DiskCacheStrategy.NONE:表示不缓存任何内容。 
  7. //DiskCacheStrategy.SOURCE:表示只缓存原始图片。 
  8. //DiskCacheStrategy.RESULT:表示只缓存转换过后的图片(默认选项)。 
  9. //DiskCacheStrategy.ALL :表示既缓存原始图片,也缓存转换过后的图片。 

10、当引用的 url 存在 token 时解决方法

  1. public class MyGlideUrl extends GlideUrl { 
  2.     private String mUrl; 
  3.     public MyGlideUrl(String url) { 
  4.         super(url); 
  5.         mUrl = url; 
  6.     } 
  7.     @Override 
  8.     public String getCacheKey() { 
  9.         return mUrl.replace(findTokenParam(), ""); 
  10.     } 
  11.     private String findTokenParam() { 
  12.         String tokenParam = ""
  13.         int tokenKeyIndex = mUrl.indexOf("?token=") >= 0 ? mUrl.indexOf("?token=") : mUrl.indexOf("&token="); 
  14.         if (tokenKeyIndex != -1) { 
  15.             int nextAndIndex = mUrl.indexOf("&", tokenKeyIndex + 1); 
  16.             if (nextAndIndex != -1) { 
  17.                 tokenParam = mUrl.substring(tokenKeyIndex + 1, nextAndIndex + 1); 
  18.             } else { 
  19.                 tokenParam = mUrl.substring(tokenKeyIndex); 
  20.             } 
  21.         } 
  22.         return tokenParam; 
  23.     } 

然后加载图片的方式为:

  1. Glide.with(this) 
  2.      .load(new MyGlideUrl(url)) 
  3.      .into(imageView); 

11、利用Glide将图片加载到不同控件或加载成不同使用方式

(1)、拿到图片实例

  1. //1、通过自己构造 target 可以获取到图片实例 
  2. SimpleTarget simpleTarget = new SimpleTarget() { 
  3.     @Override 
  4.     public void onResourceReady(GlideDrawable resource, GlideAnimation glideAnimation) { 
  5.         imageView.setImageDrawable(resource); 
  6.     } 
  7. }; 
  8. //2、将图片实例记载到指定的imageview上,也可以做其他的事情 
  9. public void loadImage(View view) { 
  10.     String url = "http://cn.bing.com/az/hprichbg/rb/TOAD_ZH-CN7336795473_1920x1080.jpg"
  11.     Glide.with(this) 
  12.          .load(url) 
  13.          .into(simpleTarget); 

(2)、将图片加载到任何位置

  1.  
  2. public class MyLayout extends LinearLayout { 
  3.     private ViewTarget viewTarget; 
  4.     public MyLayout(Context context, AttributeSet attrs) { 
  5.         super(context, attrs); 
  6.         viewTarget = new ViewTarget(this) { 
  7.             @Override 
  8.             public void onResourceReady(GlideDrawable resource, GlideAnimation glideAnimation) { 
  9.                 MyLayout myLayout = getView(); 
  10.                 myLayout.setImageAsBackground(resource); 
  11.             } 
  12.         }; 
  13.     } 
  14.     public ViewTarget getTarget() { 
  15.         return viewTarget; 
  16.     } 
  17.     public void setImageAsBackground(GlideDrawable resource) { 
  18.         setBackground(resource); 
  19.     } 
  20. //引用图片到指定控件作为背景 
  21. public class MainActivity extends AppCompatActivity { 
  22.     MyLayout myLayout; 
  23.     @Override 
  24.     protected void onCreate(Bundle savedInstanceState) { 
  25.         super.onCreate(savedInstanceState); 
  26.         setContentView(R.layout.activity_main); 
  27.         myLayout = (MyLayout) findViewById(R.id.background); 
  28.     } 
  29.     public void loadImage(View view) { 
  30.         String url = "http://cn.bing.com/az/hprichbg/rb/TOAD_ZH-CN7336795473_1920x1080.jpg"
  31.         Glide.with(this) 
  32.              .load(url) 
  33.              .into(myLayout.getTarget()); 
  34.     } 

12、Glide 实现预加载

  1. //a、预加载代码 
  2. Glide.with(this) 
  3.      .load(url) 
  4.      .diskCacheStrategy(DiskCacheStrategy.SOURCE) 
  5.      .preload(); 
  6. //preload() 有两种重载 
  7.  // 1、带有参数的重载,参数作用是设置预加载的图片大小; 
  8. //2、不带参数的表示加载的图片为原始尺寸; 
  9. //b、使用预加载的图片 
  10. Glide.with(this) 
  11.      .load(url) 
  12.      .diskCacheStrategy(DiskCacheStrategy.SOURCE) 
  13.      .into(imageView); 

二、Glide加载流程详解

1、with(context)

  1. // Glide.java 
  2. public static RequestManager with(@NonNull Context context) { 
  3.     return getRetriever(context).get(context); 
  4. public static RequestManager with(@NonNull Activity activity) { 
  5.     return getRetriever(activity).get(activity); 
  6. public static RequestManager with(@NonNull FragmentActivity activity) { 
  7.     return getRetriever(activity).get(activity); 
  8. public static RequestManager with(@NonNull Fragment fragment) { 
  9.     return getRetriever(fragment.getContext()).get(fragment); 
  10. public static RequestManager with(@NonNull View view) { 
  11.     return getRetriever(view.getContext()).get(view); 

该函数创建了Glide实例并初始化了一些基本参数,然后创建了一个RequestManager对象并返回。总共有5个场景,这里就先选取参数为Context类型情形进行分析。

  1. // Glide.java 
  2. public static RequestManager with(@NonNull Context context) { 
  3.     return getRetriever(context).get(context); 

可以看到该函数首先调用了getRetriever(context)获取到了RequestManagerRetriever对象。在创建该对象之前首先通过Glide.java中的get方法获得了Glide实例(Glide是一个单例),同时读取AppGlideModule和AndroidManifest.xml的配置。

  1. // Glide.java 
  2. private static RequestManagerRetriever getRetriever(@Nullable Context context) { 
  3.     // Glide.get(context)获取Glide实例 
  4.     return Glide.get(context).getRequestManagerRetriever(); 
  5. public static Glide get(@NonNull Context context) { 
  6.     if (glide == null) { 
  7.       // 加载AppGlideModule 
  8.       GeneratedAppGlideModule annotationGeneratedModule = 
  9.           getAnnotationGeneratedGlideModules(context.getApplicationContext()); 
  10.       synchronized (Glide.class) { 
  11.         if (glide == null) { 
  12.           // 加载Mainfest配置、注册模块回调 
  13.           // 这一步执行了 Glide.build()方法构造Glide实例。build方法下面会讲到 
  14.           checkAndInitializeGlide(context, annotationGeneratedModule); 
  15.         } 
  16.       } 
  17.     } 
  18.     return glide; 
  19.   } 

获取到Glide实例后,紧接着调用getRequestManagerRetriever方法返回了上一步已经初始化好的RequestManagerRetriever对象。

  1. // Glide.java 
  2.   public RequestManagerRetriever getRequestManagerRetriever() { 
  3.     return requestManagerRetriever; 
  4.   } 

接着再看一看RequestManagerRetriever是如何被初始化的,以及初始化过程中都干了哪些事。首先贴源码看看Glide.build方法内部具体实现(该方法在上述checkAndInitializeGlide()函数中被调用):

  1. // GlideBuilder.java 
  2. Glide build(@NonNull Context context) { 
  3.       // 分配线程池、配置缓存策略 
  4.       sourceExecutor = GlideExecutor.newSourceExecutor(); 
  5.       diskCacheExecutor = GlideExecutor.newDiskCacheExecutor(); 
  6.       animationExecutor = GlideExecutor.newAnimationExecutor(); 
  7.       memorySizeCalculator = new MemorySizeCalculator.Builder(context).build(); 
  8.       // 监听网络变化 
  9.       connectivityMonitorFactory = new DefaultConnectivityMonitorFactory(); 
  10.       int size = memorySizeCalculator.getBitmapPoolSize(); 
  11.       if (size > 0) { 
  12.         bitmapPool = new LruBitmapPool(size); 
  13.       } else { 
  14.         bitmapPool = new BitmapPoolAdapter(); 
  15.       } 
  16.       arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes()); 
  17.       memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize()); 
  18.       diskCacheFactory = new InternalCacheDiskCacheFactory(context); 
  19.     // engine是负责执行加载任务的 
  20.     if (engine == null) { 
  21.       engine = 
  22.           new Engine( 
  23.               memoryCache, 
  24.               diskCacheFactory, 
  25.               diskCacheExecutor, 
  26.               sourceExecutor, 
  27.               GlideExecutor.newUnlimitedSourceExecutor(), 
  28.               animationExecutor, 
  29.               isActiveResourceRetentionAllowed); 
  30.     } 
  31.     if (defaultRequestListeners == null) { 
  32.       defaultRequestListeners = Collections.emptyList(); 
  33.     } else { 
  34.       defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners); 
  35.     } 
  36.     RequestManagerRetriever requestManagerRetriever = 
  37.         new RequestManagerRetriever(requestManagerFactory); 
  38.     return new Glide( 
  39.         context, 
  40.         engine, 
  41.         memoryCache, 
  42.         bitmapPool, 
  43.         arrayPool, 
  44.         requestManagerRetriever, 
  45.         connectivityMonitorFactory, 
  46.         logLevel, 
  47.         defaultRequestOptionsFactory, 
  48.         defaultTransitionOptions, 
  49.         defaultRequestListeners, 
  50.         isLoggingRequestOriginsEnabled, 
  51.         isImageDecoderEnabledForBitmaps); 
  52.   } 
  1. // RequestManagerRetriever.java 
  2. // get有好几个重载方法,这里仅选取context参数进行分析 
  3. public RequestManager get(@NonNull Context context) { 
  4.     if (Util.isOnMainThread() && !(context instanceof Application)) { 
  5.       if (context instanceof FragmentActivity) { 
  6.         return get((FragmentActivity) context); 
  7.       } else if (context instanceof Activity) { 
  8.         return get((Activity) context); 
  9.       } else if (context instanceof ContextWrapper 
  10.           && ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) { 
  11.         return get(((ContextWrapper) context).getBaseContext()); 
  12.       } 
  13.     } 
  14.     return getApplicationManager(context); 
  15.   } 

执行完Glide.with(context)后我们拿到了一个对应的RequestManager对象,接下来就执行下一个任务load(url);

2、load(url)

拿到了RequestManager,紧接着调用load方法开始执行下一步操作,同样先看看load方法的实现

  1. // RequestManager.java 
  2. public RequestBuilder load(@Nullable Bitmap bitmap) { 
  3.     return asDrawable().load(bitmap); 
  4.   } 
  5.   public RequestBuilder load(@Nullable Drawable drawable) { 
  6.     return asDrawable().load(drawable); 
  7.   } 
  8.   public RequestBuilder load(@Nullable String string) { 
  9.     return asDrawable().load(string); 
  10.   } 
  11.   public RequestBuilder load(@Nullable Uri uri) { 
  12.     return asDrawable().load(uri); 
  13.   } 
  14.   public RequestBuilder load(@Nullable File file) { 
  15.     return asDrawable().load(file); 
  16.   } 
  17.   public RequestBuilder load(@RawRes @DrawableRes @Nullable Integer resourceId) { 
  18.     return asDrawable().load(resourceId); 
  19.   } 
  20.   public RequestBuilder load(@Nullable URL url) { 
  21.     return asDrawable().load(url); 
  22.   } 
  23.   public RequestBuilder load(@Nullable byte[] model) { 
  24.     return asDrawable().load(model); 
  25.   } 
  26.   public RequestBuilder load(@Nullable Object model) { 
  27.     return asDrawable().load(model); 
  28.   } 
  1. // RequestManager.java 
  2.   public RequestBuilder asDrawable() { 
  3.     return as(Drawable.class); 
  4.   } 
  5.   public  RequestBuilder as(@NonNull Class resourceClass) { 
  6.     return new RequestBuilder<>(glide, this, resourceClass, context); 
  7.   } 

asDrawable方法创建了RequestBuilder对象,然后调用RequestBuilder.java中的load方法;

  1. // RequestBuilder.java 
  2.   // 传入的String类型的url将会被作为缓存的key 
  3.   public RequestBuilder load(@Nullable String string) { 
  4.     return loadGeneric(string); 
  5.   } 
  6.   // 这里返回了自身 
  7.   private RequestBuilder loadGeneric(@Nullable Object model) { 
  8.     this.model = model; 
  9.     isModelSet = true
  10.     return this; 
  11.   } 

load函数主要工作就是根据传入的资源类型,构造了一个相应的RequestBuilder对象。至此一切准备工作准备就绪,接下来就是最为重要的一步了-加载、展示文件,让我们来着看into(view)方法如何完成这些任务;

3、into(view)

拿到的是对应类型RequestBuilder实例,那么就看看该类里into方法的具体实现。同样into方法有into(@NonNull Y target)和into(@NonNull ImageView )两个重载函数(这两个函数最终都会走到同一个函数中),由于调用into方法时我们传入的参数是ImageView类型的;

  1. // RequestBuilder.java 
  2.   public ViewTarget into(@NonNull ImageView view) { 
  3.     Util.assertMainThread(); 
  4.     BaseRequestOptions requestOptions = this; 
  5.     // View's scale type. 
  6.     // 处理图片缩放,根据缩放类型来初始化对应的requestOptions对象 
  7.     ...... 
  8.     return into
  9.         glideContext.buildImageViewTarget(view, transcodeClass), 
  10.          null
  11.         requestOptions, 
  12.         Executors.mainThreadExecutor() // 运行在主线程的handler 
  13.     ); 
  14.   } 
  1. // GlideContext.java 
  2.   public  ViewTarget buildImageViewTarget(@NonNull ImageView imageView, @NonNull Class transcodeClass) { 
  3.     return imageViewTargetFactory.buildTarget(imageView, transcodeClass); 
  4.   } 

ViewTarget又是由ImageViewTargetFactory工厂方法生成,接着再看buildTarget方法是如何生成ViewTarget对象。

  1. // imageViewTargetFactory.java 
  2. public class ImageViewTargetFactory { 
  3.   public  ViewTarget buildTarget(@NonNull ImageView view, @NonNull Class clazz) { 
  4.     if (Bitmap.class.equals(clazz)) { 
  5.       return (ViewTarget) new BitmapImageViewTarget(view); 
  6.     } else if (Drawable.class.isAssignableFrom(clazz)) { 
  7.       return (ViewTarget) new DrawableImageViewTarget(view); 
  8.     } else { 
  9.       throw new IllegalArgumentException("Unhandled class: " + clazz + ", try .as(Class).transcode(ResourceTranscoder)"); 
  10.     } 
  11.   } 

可以看到无论传入参数是何种类型,最终都会转换成两种类型的ViewTarget :BitmapImageViewTarget;DrawableImageViewTarget;这里如何选择取决于asBitmap()、asGif()和asDrawable()函数是否被调用,默认是Bitmap类型,所以这里默认返回的是BitmapImageViewTarget;

  1. // BitmapImageViewTarget.java 
  2. public class BitmapImageViewTarget extends ImageViewTarget { 
  3.   public BitmapImageViewTarget(ImageView view) { 
  4.     super(view); 
  5.   } 
  6.   @Override 
  7.   protected void setResource(Bitmap resource) { 
  8.     view.setImageBitmap(resource); // 显示图片 
  9.   } 

至此ViewTarget创建完毕,我们再回到RequestBuilder.java私有into方法

  1. // RequestBuilder.java` 
  2.  private > Y into
  3.       @NonNull Y target, 
  4.       @Nullable RequestListener targetListener, 
  5.       BaseRequestOptions options, 
  6.       Executor callbackExecutor) { 
  7.     // 注释1:创建request 
  8.     Request request = buildRequest(target, targetListener, options, callbackExecutor); 
  9.     // 获取前一个reqeust请求对象 
  10.     Request previous = target.getRequest(); 
  11.     // 与上一个请求相同 并且 上一个请求已完成 
  12.     if (request.isEquivalentTo(previous)&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) { 
  13.      // 上一个请求已完成,那么重新启动它 
  14.       if (!Preconditions.checkNotNull(previous).isRunning()) { 
  15.         previous.begin(); 
  16.       } 
  17.       return target; 
  18.     } 
  19.     // 与上一个请求不同,则清除掉上一个,再将加入新请求 
  20.     requestManager.clear(target); 
  21.     target.setRequest(request); 
  22.     requestManager.track(target, request); 
  23.     return target; 
  24.   } 

顺着代码次序,来看看这个方法每一步都干了什么:

  1. // ReqeustManager.java   
  2. synchronized void track(@NonNull Target target, @NonNull Request request) { 
  3.     // 与lifecycle绑定 
  4.     targetTracker.track(target); 
  5.     // 启动reqeust 
  6.     requestTracker.runRequest(request); 
  7.   } 
  8. // RequestTracker.java 
  9.   public void runRequest(@NonNull Request request) { 
  10.     requests.add(request); 
  11.     if (!isPaused) { 
  12.       request.begin(); // 立即开始加载 
  13.     } else { 
  14.       //防止从以前的请求中加载任何位图,释放该请求所拥有的任何资源,显示当前占位符(如果提供了该占位符),并将该请求标记为已取消。 
  15.       // request.java( Interface ) 
  16.       request.clear(); 
  17.       pendingRequests.add(request); // 加入队列等待执行 
  18.     } 
  19.   } 
  1. // RequestBuilder.java 
  2. private Request buildRequest( 
  3.       Target target, 
  4.       @Nullable RequestListener targetListener, 
  5.       BaseRequestOptions requestOptions, 
  6.       Executor callbackExecutor) { 
  7.     return buildRequestRecursive( 
  8.          new Object(), 
  9.         target, 
  10.         targetListener, 
  11.          null
  12.         transitionOptions, 
  13.         requestOptions.getPriority(), 
  14.         requestOptions.getOverrideWidth(), 
  15.         requestOptions.getOverrideHeight(), 
  16.         requestOptions, 
  17.         callbackExecutor); 
  18.   } 
  19. private Request buildRequestRecursive( 
  20.       Object requestLock, 
  21.       Target target, 
  22.       @Nullable RequestListener targetListener, 
  23.       @Nullable RequestCoordinator parentCoordinator, 
  24.       TransitionOptions transitionOptions, 
  25.       Priority priority, 
  26.       int overrideWidth, 
  27.       int overrideHeight, 
  28.       BaseRequestOptions requestOptions, 
  29.       Executor callbackExecutor) { 
  30.     // Build the ErrorRequestCoordinator first if necessary so we can update parentCoordinator. 
  31.     ErrorRequestCoordinator errorRequestCoordinator = null
  32.     // 请求出错了 
  33.     if (errorBuilder != null) { 
  34.       errorRequestCoordinator = new ErrorRequestCoordinator(requestLock, parentCoordinator); 
  35.       parentCoordinator = errorRequestCoordinator; 
  36.     } 
  37.     // 无法确认完成请求和缩略图请求哪个先完成,所以当缩略图比完成请求后完成时就不再显示缩略图 
  38.     Request mainRequest = 
  39.         buildThumbnailRequestRecursive( 
  40.             requestLock, 
  41.             target, 
  42.             targetListener, 
  43.             parentCoordinator, 
  44.             transitionOptions, 
  45.             priority, 
  46.             overrideWidth, 
  47.             overrideHeight, 
  48.             requestOptions, 
  49.             callbackExecutor); 
  50.     // 请求成功了,直接返回缩略图Request 
  51.     if (errorRequestCoordinator == null) { 
  52.       return mainRequest; 
  53.     } 
  54.     // ... 
  55.     Request errorRequest = 
  56.         errorBuilder.buildRequestRecursive( 
  57.             requestLock, 
  58.             target, 
  59.             targetListener, 
  60.             errorRequestCoordinator, 
  61.             errorBuilder.transitionOptions, 
  62.             errorBuilder.getPriority(), 
  63.             errorOverrideWidth, 
  64.             errorOverrideHeight, 
  65.             errorBuilder, 
  66.             callbackExecutor); 
  67.     // 同时返回缩略图请求和错误请求 
  68.     errorRequestCoordinator.setRequests(mainRequest, errorRequest); 
  69.     return errorRequestCoordinator; 
  70.   } 

显然代码里的mainRequest就是我们要找的Request了,它是由buildThumbnailRequestRecursive方法返回的,深入其内部我们发现Request最终其实是由SingleRequest.obtain方法产生,也就是说我们最终拿到的Request其实就是SingleReqeust类的一个实例。这里过程比较简单,代码就不贴出来了。我们直接去SingleReqeust类里面 看看begin方法如何实现的;

  1. // SingleReqeust.java 
  2. public void begin() { 
  3.       if (status == Status.COMPLETE) { 
  4.         // 资源已下载,直接回调 
  5.         // 执行动画 
  6.         onResourceReady(resource, DataSource.MEMORY_CACHE); 
  7.         return
  8.       } 
  9.         // 计算尺寸 
  10.       if (Util.isValidDimensions(overrideWidth, overrideHeight)) { 
  11.         onSizeReady(overrideWidth, overrideHeight); 
  12.       } else { 
  13.         target.getSize(this); 
  14.       } 
  15.       if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE) 
  16.           && canNotifyStatusChanged()) { 
  17.         // 开始加载 
  18.         // 设置占位度 
  19.         target.onLoadStarted(getPlaceholderDrawable()); 
  20.       } 
  21.   } 

进入begin方法后首先判断如果资源已经过加载好了则直接回调onResourceReady显示图片并缓存,否则测量出图片尺寸后再开始加载图片(onSizeReady()中执行加载任务)并同时显示占位图:

①overrideWith、overrideHeight通过override(width, height)设置:

Glide.with(mContext).load(url).override(75, 75).into(imageView);

②占位图是用户调用placeholder(resId)设置:

Glide.with(mContext).load(url).placeholder(resId).into(imageView);

接着再看onSizeReady()测量完图片尺寸后如何加载图片的:

  1. // SingleRequest.java 
  2. @Override 
  3.   public void onSizeReady(int width, int height) { 
  4.       if (status != Status.WAITING_FOR_SIZE) { 
  5.         return
  6.       } 
  7.       status = Status.RUNNING; 
  8.       // 获取图片尺寸 
  9.       float sizeMultiplier = requestOptions.getSizeMultiplier(); 
  10.       this.width = maybeApplySizeMultiplier(width, sizeMultiplier); 
  11.       this.height = maybeApplySizeMultiplier(height, sizeMultiplier); 
  12.       // 开始加载任务 
  13.       loadStatus = 
  14.           engine.load
  15.               glideContext, 
  16.               model, 
  17.               requestOptions.getSignature(), 
  18.               this.width, 
  19.               this.height, 
  20.               requestOptions.getResourceClass(), 
  21.               transcodeClass, 
  22.               priority, 
  23.               requestOptions.getDiskCacheStrategy(), 
  24.               requestOptions.getTransformations(), 
  25.               requestOptions.isTransformationRequired(), 
  26.               requestOptions.isScaleOnlyOrNoTransform(), 
  27.               requestOptions.getOptions(), 
  28.               requestOptions.isMemoryCacheable(), 
  29.               requestOptions.getUseUnlimitedSourceGeneratorsPool(), 
  30.               requestOptions.getUseAnimationPool(), 
  31.               requestOptions.getOnlyRetrieveFromCache(), 
  32.               this, 
  33.               callbackExecutor); 
  34.   } 

总结

Glide初始化、显示占位图、图片封面的整个业务流程都走完了;

可以从中学习glide中的设计模式:单例模式、工厂方法、策略模式等等,发现自己的不足之处;

 

Glide的图片缓存可以看上一篇文章

 

来源:Android开发编程内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯