Android Glide设置默认图片、异常图片为圆形图片

亦凉 2022-06-07 00:35 395阅读 0赞

Android Glide4 异步图片框架

  • 简介篇: Glide框架
  • 迁移篇:Glide V4 框架新特性(Migrating from v3 to v4)
  • 基础篇:Android开发中使用Glide V4 中Generated API特性
  • 进级篇:Kotlin编程开发之Glide V4使用OkHttp3作为传输层

前言

在项目开发中,是需要经常用到圆形图片的,设置默认图片,设置资源图片等等。

若是,异常图片,默认图片都需要美工妹子做成圆形图片,无疑增加了美工妹子的工作量。本着当活雷锋的思想,程序员能搞定的事情,绝不麻烦美工妹子。

要说图片异步加载框架,现今最流行的非Glide莫属,连谷歌I/O App都在使用,可见它的强大之处。

根据源码走向找到,设置默认图片,异常图片的方法

众所周知,Glide的开启加载是通过调用GlideApp.with().....into()或者preload().


1. 首先,进入RequestBuilder类#into():

  1. /** * Set the target the resource will be loaded into. * * @param target The target to load the resource into. * @return The given target. * @see RequestManager#clear(Target) */
  2. public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) {
  3. Util.assertMainThread();
  4. Preconditions.checkNotNull(target);
  5. if (!isModelSet) {
  6. throw new IllegalArgumentException("You must call #load() before calling #into()");
  7. }
  8. Request previous = target.getRequest();
  9. if (previous != null) {
  10. requestManager.clear(target);
  11. }
  12. requestOptions.lock();
  13. Request request = buildRequest(target);
  14. target.setRequest(request);
  15. requestManager.track(target, request);
  16. return target;
  17. }

2. 接下,源码来走向到RequestManager类中track():

  1. void track(Target<?> target, Request request) {
  2. targetTracker.track(target);
  3. requestTracker.runRequest(request);
  4. }

3. 在接下来,源码走向到RequestTracker类中runRequest():

  1. /** * Starts tracking the given request. */
  2. public void runRequest(Request request) {
  3. requests.add(request);
  4. if (!isPaused) {
  5. request.begin();
  6. } else {
  7. pendingRequests.add(request);
  8. }
  9. }

4. 最终走向到SingleRequest类中begin():

  1. @Override
  2. public void begin() {
  3. stateVerifier.throwIfRecycled();
  4. startTime = LogTime.getLogTime();
  5. if (model == null) {
  6. if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
  7. width = overrideWidth;
  8. height = overrideHeight;
  9. }
  10. // Only log at more verbose log levels if the user has set a fallback drawable, because
  11. // fallback Drawables indicate the user expects null models occasionally.
  12. int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
  13. onLoadFailed(new GlideException("Received null model"), logLevel);
  14. return;
  15. }
  16. status = Status.WAITING_FOR_SIZE;
  17. if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
  18. onSizeReady(overrideWidth, overrideHeight);
  19. } else {
  20. target.getSize(this);
  21. }
  22. if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
  23. && canNotifyStatusChanged()) {
  24. target.onLoadStarted(getPlaceholderDrawable());
  25. }
  26. if (Log.isLoggable(TAG, Log.VERBOSE)) {
  27. logV("finished run method in " + LogTime.getElapsedMillis(startTime));
  28. }
  29. }

可以从源码target.onLoadStarted(getPlaceholderDrawable())发觉,最后是通过Target对象的onLoadStarted()方法来设置默认空白图片的。

SingleRequest类中设置异常图片的源码

  1. private void setErrorPlaceholder() {
  2. if (!canNotifyStatusChanged()) {
  3. return;
  4. }
  5. Drawable error = null;
  6. if (model == null) {
  7. error = getFallbackDrawable();
  8. }
  9. // Either the model isn't null, or there was no fallback drawable set.
  10. if (error == null) {
  11. error = getErrorDrawable();
  12. }
  13. // The model isn't null, no fallback drawable was set or no error drawable was set.
  14. if (error == null) {
  15. error = getPlaceholderDrawable();
  16. }
  17. target.onLoadFailed(error);
  18. }

可以从源码target.onLoadFailed(error)可知,是通过Target对象的onLoadFailed()方法来设置异常图片的。

长征路已经走完一半,已经找到了最后的源码走向。剩下来,只需要自定义一个Target子类。

Glide中已经存在一个ImageViewTarget类,查看源码如下

  1. public abstract class ImageViewTarget<Z> extends ViewTarget<ImageView, Z>
  2. implements Transition.ViewAdapter {
  3. @Nullable
  4. private Animatable animatable;
  5. public ImageViewTarget(ImageView view) {
  6. super(view);
  7. }
  8. /** * Returns the current { @link android.graphics.drawable.Drawable} being displayed in the view * using { @link android.widget.ImageView#getDrawable()}. */
  9. @Override
  10. @Nullable
  11. public Drawable getCurrentDrawable() {
  12. return view.getDrawable();
  13. }
  14. /** * Sets the given { @link android.graphics.drawable.Drawable} on the view using { @link * android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}. * * @param drawable { @inheritDoc} */
  15. @Override
  16. public void setDrawable(Drawable drawable) {
  17. view.setImageDrawable(drawable);
  18. }
  19. /** * Sets the given { @link android.graphics.drawable.Drawable} on the view using { @link * android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}. * * @param placeholder { @inheritDoc} */
  20. @Override
  21. public void onLoadStarted(@Nullable Drawable placeholder) {
  22. super.onLoadStarted(placeholder);
  23. setResourceInternal(null);
  24. setDrawable(placeholder);
  25. }
  26. /** * Sets the given { @link android.graphics.drawable.Drawable} on the view using { @link * android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}. * * @param errorDrawable { @inheritDoc} */
  27. @Override
  28. public void onLoadFailed(@Nullable Drawable errorDrawable) {
  29. super.onLoadFailed(errorDrawable);
  30. setResourceInternal(null);
  31. setDrawable(errorDrawable);
  32. }
  33. /** * Sets the given { @link android.graphics.drawable.Drawable} on the view using { @link * android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}. * * @param placeholder { @inheritDoc} */
  34. @Override
  35. public void onLoadCleared(@Nullable Drawable placeholder) {
  36. super.onLoadCleared(placeholder);
  37. setResourceInternal(null);
  38. setDrawable(placeholder);
  39. }
  40. @Override
  41. public void onResourceReady(Z resource, @Nullable Transition<? super Z> transition) {
  42. if (transition == null || !transition.transition(resource, this)) {
  43. setResourceInternal(resource);
  44. } else {
  45. maybeUpdateAnimatable(resource);
  46. }
  47. }
  48. @Override
  49. public void onStart() {
  50. if (animatable != null) {
  51. animatable.start();
  52. }
  53. }
  54. @Override
  55. public void onStop() {
  56. if (animatable != null) {
  57. animatable.stop();
  58. }
  59. }
  60. private void setResourceInternal(@Nullable Z resource) {
  61. maybeUpdateAnimatable(resource);
  62. setResource(resource);
  63. }
  64. private void maybeUpdateAnimatable(@Nullable Z resource) {
  65. if (resource instanceof Animatable) {
  66. animatable = (Animatable) resource;
  67. animatable.start();
  68. } else {
  69. animatable = null;
  70. }
  71. }
  72. protected abstract void setResource(@Nullable Z resource);
  73. }

从源码可知,无论是空白图片,还是异常图片都是最后走向到setDrawable(Drawable drawable)

源码寻找之路已经走完,马上就可以实现自己需要的需求,继续撸起。

定义一个默认,异常,资源图片都为圆形的 ImageViewTarget子类


分析

  • 定义ImageViewTarget子类:
  • 重写setDrawable(Drawable drawable),异常,默认空白图片设置为圆形。
  • 实现抽象方法setResource( Bitmap resource),正常加载的资源图片设置为圆形

代码编写如下

  1. /** * * 设置 默认图片,异常图片,指定路径的图片为圆角图片 */
  2. public class CircleBitmapTarget extends ImageViewTarget<Bitmap> {
  3. public CircleBitmapTarget(ImageView view) {
  4. super(view);
  5. }
  6. /** * 从指定路径加载的Bitmap * @param resource */
  7. @Override
  8. protected void setResource(@Nullable Bitmap resource) {
  9. bindCircleBitmapToImageView(resource);
  10. }
  11. /** * * onLoadFailed()和onLoadStarted调用该方法,用于设置默认的图片和异常图片 * 设置默认图片 * @param drawable */
  12. @Override
  13. public void setDrawable(Drawable drawable) {
  14. if (drawable instanceof BitmapDrawable){
  15. Bitmap bitmap1= ((BitmapDrawable) drawable).getBitmap();
  16. bindCircleBitmapToImageView(bitmap1);
  17. }else{
  18. view.setImageDrawable(drawable);
  19. }
  20. }
  21. /** * 通过RoundedBitmapDrawable绘制圆形Bitmap,且加载ImageView. * @param bitmap */
  22. private void bindCircleBitmapToImageView(Bitmap bitmap){
  23. RoundedBitmapDrawable bitmapDrawable= RoundedBitmapDrawableFactory.create(view.getContext().getResources(),bitmap);
  24. bitmapDrawable.setCircular(true);
  25. view.setImageDrawable(bitmapDrawable);
  26. }
  27. }

最后使用方式

  1. GlideRequest<Bitmap> glideRequest = GlideApp.with(context).asBitmap();
  2. glideRequest.load(imageUrl).error(errorResourceId)//异常时候显示的图片
  3. .placeholder(placeResourceId)//加载成功前显示的图片
  4. .fallback(nullResourceId)//url为空的时候,显示的图片
  5. .into(new CircleBitmapTarget(imageView));//在RequestBuilder<Bitmap> 中使用自定义的ImageViewTarget

发表评论

表情:
评论列表 (有 0 条评论,395人围观)

还没有评论,来说两句吧...

相关阅读