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

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():

  /**
   * 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)
   */
  public > Y into(@NonNull Y target) {
    Util.assertMainThread();
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }

    Request previous = target.getRequest();

    if (previous != null) {
      requestManager.clear(target);
    }

    requestOptions.lock();
    Request request = buildRequest(target);
    target.setRequest(request);
    requestManager.track(target, request);

    return target;
  }

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

  void track(Target target, Request request) {
    targetTracker.track(target);
    requestTracker.runRequest(request);
  }

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

  /**
   * Starts tracking the given request.
   */
  public void runRequest(Request request) {
    requests.add(request);
    if (!isPaused) {
      request.begin();
    } else {
      pendingRequests.add(request);
    }
  }

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

@Override
public void begin() {
    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;
    }

    status = Status.WAITING_FOR_SIZE;
    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 (Log.isLoggable(TAG, Log.VERBOSE)) {
      logV("finished run method in " + LogTime.getElapsedMillis(startTime));
    }
}

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

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

  private void setErrorPlaceholder() {
    if (!canNotifyStatusChanged()) {
      return;
    }

    Drawable error = null;
    if (model == null) {
      error = getFallbackDrawable();
    }
    // Either the model isn't null, or there was no fallback drawable set.
    if (error == null) {
      error = getErrorDrawable();
    }
    // The model isn't null, no fallback drawable was set or no error drawable was set.
    if (error == null) {
      error = getPlaceholderDrawable();
    }
    target.onLoadFailed(error);
  }

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

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

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

public abstract class ImageViewTarget<Z> extends ViewTarget<ImageView, Z>
    implements Transition.ViewAdapter {

  @Nullable
  private Animatable animatable;

  public ImageViewTarget(ImageView view) {
    super(view);
  }

  /**
   * Returns the current {@link android.graphics.drawable.Drawable} being displayed in the view
   * using {@link android.widget.ImageView#getDrawable()}.
   */
  @Override
  @Nullable
  public Drawable getCurrentDrawable() {
    return view.getDrawable();
  }

  /**
   * Sets the given {@link android.graphics.drawable.Drawable} on the view using {@link
   * android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}.
   *
   * @param drawable {@inheritDoc}
   */
  @Override
  public void setDrawable(Drawable drawable) {
    view.setImageDrawable(drawable);
  }

  /**
   * Sets the given {@link android.graphics.drawable.Drawable} on the view using {@link
   * android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}.
   *
   * @param placeholder {@inheritDoc}
   */
  @Override
  public void onLoadStarted(@Nullable Drawable placeholder) {
    super.onLoadStarted(placeholder);
    setResourceInternal(null);
    setDrawable(placeholder);
  }

  /**
   * Sets the given {@link android.graphics.drawable.Drawable} on the view using {@link
   * android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}.
   *
   * @param errorDrawable {@inheritDoc}
   */
  @Override
  public void onLoadFailed(@Nullable Drawable errorDrawable) {
    super.onLoadFailed(errorDrawable);
    setResourceInternal(null);
    setDrawable(errorDrawable);
  }

  /**
   * Sets the given {@link android.graphics.drawable.Drawable} on the view using {@link
   * android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}.
   *
   * @param placeholder {@inheritDoc}
   */
  @Override
  public void onLoadCleared(@Nullable Drawable placeholder) {
    super.onLoadCleared(placeholder);
    setResourceInternal(null);
    setDrawable(placeholder);
  }

  @Override
  public void onResourceReady(Z resource, @Nullable Transitionsuper Z> transition) {
    if (transition == null || !transition.transition(resource, this)) {
      setResourceInternal(resource);
    } else {
      maybeUpdateAnimatable(resource);
    }
  }

  @Override
  public void onStart() {
    if (animatable != null) {
      animatable.start();
    }
  }

  @Override
  public void onStop() {
    if (animatable != null) {
      animatable.stop();
    }
  }

  private void setResourceInternal(@Nullable Z resource) {
    maybeUpdateAnimatable(resource);
    setResource(resource);
  }

  private void maybeUpdateAnimatable(@Nullable Z resource) {
    if (resource instanceof Animatable) {
      animatable = (Animatable) resource;
      animatable.start();
    } else {
      animatable = null;
    }
  }

  protected abstract void setResource(@Nullable Z resource);
}

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

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

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


分析

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

代码编写如下

/**
 *
 * 设置 默认图片,异常图片,指定路径的图片为圆角图片
 */

public class CircleBitmapTarget extends ImageViewTarget<Bitmap> {
    public CircleBitmapTarget(ImageView view) {
        super(view);
    }

    /**
     *  从指定路径加载的Bitmap
     * @param resource
     */
    @Override
    protected void setResource(@Nullable Bitmap resource) {
         bindCircleBitmapToImageView(resource);
    }
    /**
     *
     * onLoadFailed()和onLoadStarted调用该方法,用于设置默认的图片和异常图片
     * 设置默认图片
     * @param drawable
     */
    @Override
    public void setDrawable(Drawable drawable) {
        if (drawable instanceof BitmapDrawable){
           Bitmap bitmap1= ((BitmapDrawable) drawable).getBitmap();
          bindCircleBitmapToImageView(bitmap1);
        }else{
            view.setImageDrawable(drawable);
        }
    }

    /**
     * 通过RoundedBitmapDrawable绘制圆形Bitmap,且加载ImageView.
     * @param bitmap
     */
    private void bindCircleBitmapToImageView(Bitmap bitmap){
        RoundedBitmapDrawable bitmapDrawable=  RoundedBitmapDrawableFactory.create(view.getContext().getResources(),bitmap);
        bitmapDrawable.setCircular(true);
        view.setImageDrawable(bitmapDrawable);
    }
}

最后使用方式

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

你可能感兴趣的:(Android,热门的框架与第三方SDK,Glide,V4,图片加载库)