杨说:Glide 4.11.0 发送请求准备工作

1,057 阅读7分钟

分析完Glide构造的第一个步RequesManager生命周期监听和第二步RequestBuilder请求数据的封装,现在来到第三步请求的发送

 Glide.with(this)
            .load(uri)
            .skipMemoryCache(true)
            .into(iv_activity)

目录

一、将Imanage封装成Target
二、将Target组装成Request开始请求
三、处理Target重复请求
四、发送请求

一 将Imanage封装成Target

一般我们常用的都是into到ImageView中,其实最后调用的都是into(Target)

RequestBuilder.java

private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> options,
      Executor callbackExecutor)

1.1 ImageView是如何封装成Target的

RequestBuilder.java

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.
      //根据scale type.进行请求配置赋值
      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(
    	//这里开始创建Tartget 
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        //所有的请求噢配置
        requestOptions,
        //回调线程
        Executors.mainThreadExecutor());
  }

1.2 获取通过工厂方法获取Target对象

glideContext.buildImageViewTarget(view, transcodeClass),

GlideContext.java

public <X> ViewTarget<ImageView, X> buildImageViewTarget(
     @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
   return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
 }

imageViewTargetFactory 是在创建Glide的时候new出来,然后赋值的

GlideContext.java

public GlideContext(
     @NonNull Context context,
     @NonNull ArrayPool arrayPool,
     @NonNull Registry registry,
     @NonNull ImageViewTargetFactory imageViewTargetFactory,
     @NonNull RequestOptionsFactory defaultRequestOptionsFactory,
     @NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions,
     @NonNull List<RequestListener<Object>> defaultRequestListeners,
     @NonNull Engine engine,
     boolean isLoggingRequestOriginsEnabled,
     int logLevel) {
   super(context.getApplicationContext());
   ···
   this.imageViewTargetFactory = imageViewTargetFactory;
   ···
 }
 
 Glide.java
 
 Glide(
     @NonNull Context context,
     @NonNull Engine engine,
     @NonNull MemoryCache memoryCache,
     @NonNull BitmapPool bitmapPool,
     @NonNull ArrayPool arrayPool,
     @NonNull RequestManagerRetriever requestManagerRetriever,
     @NonNull ConnectivityMonitorFactory connectivityMonitorFactory,
     int logLevel,
     @NonNull RequestOptionsFactory defaultRequestOptionsFactory,
     @NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions,
     @NonNull List<RequestListener<Object>> defaultRequestListeners,
     boolean isLoggingRequestOriginsEnabled,
     boolean isImageDecoderEnabledForBitmaps) {
   ····
   ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
   glideContext =
       new GlideContext(
           context,
           arrayPool,
           registry,
           imageViewTargetFactory,
           defaultRequestOptionsFactory,
           defaultTransitionOptions,
           defaultRequestListeners,
           engine,
           isLoggingRequestOriginsEnabled,
           logLevel);
 }

ImageViewTargetFactory是一个工厂类,根据输入类型返回对应的Tartget,之前我们在调用glideContext.buildImageViewTarget(view, transcodeClass),传入的ImageView,所以返回的是BitmapImageViewTarget

ImageViewTargetFactory

public class ImageViewTargetFactory {
 @NonNull
 @SuppressWarnings("unchecked")
 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)");
   }
 }
}

1.3 BitmapImageViewTarget

BitmapImageViewTarget.java

public class BitmapImageViewTarget extends ImageViewTarget<Bitmap> {
 // Public API.
 @SuppressWarnings("WeakerAccess")
 public BitmapImageViewTarget(ImageView view) {
   super(view);
 }

 /** @deprecated Use {@link #waitForLayout()} instead. */
 // Public API.
 @SuppressWarnings({"unused", "deprecation"})
 @Deprecated
 public BitmapImageViewTarget(ImageView view, boolean waitForLayout) {
   super(view, waitForLayout);
 }

 /**
  * Sets the {@link android.graphics.Bitmap} on the view using {@link
  * android.widget.ImageView#setImageBitmap(android.graphics.Bitmap)}.
  *
  * @param resource The bitmap to display.
  */
 @Override
 protected void setResource(Bitmap resource) {
 	//这里在请求返回成功后设置resource给ImageView
   view.setImageBitmap(resource);
 }
}

BitmapImageViewTarget是ImageViewTarget的子类,IamgerViewTarget控制显示成功内容和失败展位图,控制动画显示。

二 将Target组装成Request开始请求

我们知道,无论是into(ImageView)还是into(Target),最后调用的都是下面的方法

RequestBuilder.java

private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> options,
      Executor callbackExecutor) {
    //检测target不为null
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }
	//封装Request 2.1
    Request request = buildRequest(target, targetListener, options, callbackExecutor);

    ···
    return target;
  }

2.1 封装Request

调用Request request = buildRequest(target, targetListener, options, callbackExecutor);来封装Request

RequestBuilder.java

private Request buildRequest(
      Target<TranscodeType> target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> requestOptions,
      Executor callbackExecutor) {
    return buildRequestRecursive(
        /*requestLock=*/ new Object(),
        target,
        targetListener,
        /*parentCoordinator=*/ null,
        transitionOptions,
        requestOptions.getPriority(),
        requestOptions.getOverrideWidth(),
        requestOptions.getOverrideHeight(),
        requestOptions,
        callbackExecutor);
  }

2.2 封装主请求和错误图请求

RequestBuilder.java 
  
private Request buildRequestRecursive(
      Object requestLock,
      Target<TranscodeType> target,
      @Nullable RequestListener<TranscodeType> targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      BaseRequestOptions<?> requestOptions,
      Executor callbackExecutor) {

   ····
   ErrorRequestCoordinator errorRequestCoordinator = null;
    if (errorBuilder != null) {
      errorRequestCoordinator = new ErrorRequestCoordinator(requestLock, parentCoordinator);
      parentCoordinator = errorRequestCoordinator;
    }
   
   
   //创建主图请求包括缩略图请求
    Request mainRequest =
        buildThumbnailRequestRecursive(
            requestLock,
            target,
            targetListener,
            parentCoordinator,
            transitionOptions,
            priority,
            overrideWidth,
            overrideHeight,
            requestOptions,
            callbackExecutor);
    if (errorRequestCoordinator == null) {
      return mainRequest;
    }
	···
	//创建错误请求
    Request errorRequest =
        errorBuilder.buildRequestRecursive(
            requestLock,
            target,
            targetListener,
            errorRequestCoordinator,
            errorBuilder.transitionOptions,
            errorBuilder.getPriority(),
            errorOverrideWidth,
            errorOverrideHeight,
            errorBuilder,
            callbackExecutor);
    errorRequestCoordinator.setRequests(mainRequest, errorRequest);
    return errorRequestCoordinator;
  }

2.2.1 请求协调器的封装

上面的代码最后一行 return errorRequestCoordinator;这个errorRequestCoordinator是一个Request,也是一个RequestCoordinator请求协调器,这里采用的是责任链的模式。这句errorRequestCoordinator.setRequests(mainRequest, errorRequest);表示请求的下一个请求是errorRequest,我们看一下源码

ErrorRequestCoordinator.java

public final class ErrorRequestCoordinator implements RequestCoordinator, Request {

  private final Object requestLock;
  @Nullable private final RequestCoordinator parent;//上一个请求

  private volatile Request primary;//当前请求
  private volatile Request error;//下一个请求

  @GuardedBy("requestLock")
  private RequestState primaryState = RequestState.CLEARED;

  @GuardedBy("requestLock")
  private RequestState errorState = RequestState.CLEARED;

  public ErrorRequestCoordinator(Object requestLock, @Nullable RequestCoordinator parent) {
    this.requestLock = requestLock;
    //这里赋值,因为是主请求并带有错误请求,所以这里是null
    this.parent = parent;
  }

  public void setRequests(Request primary, Request error) {
  	//这里是主请求
    this.primary = primary;
    //错误请求
    this.error = error;
  }

  @Override
  public void begin() {
    synchronized (requestLock) {
      if (primaryState != RequestState.RUNNING) {
        primaryState = RequestState.RUNNING;
        //主请求开始请求
        primary.begin();
      }
    }
  }
 ···

  @Override
  public void onRequestSuccess(Request request) {
    synchronized (requestLock) {
     //如果主请求成功设置成功状态
      if (request.equals(primary)) {
        primaryState = RequestState.SUCCESS;
      } else if (request.equals(error)) {
      //如果错误请求成功设置成功状态
        errorState = RequestState.SUCCESS;
      }
      if (parent != null) {
      	//
        parent.onRequestSuccess(this);
      }
    }
  }

  @Override
  public void onRequestFailed(Request request) {
    synchronized (requestLock) {
    //主请求失败,设置状态
      if (!request.equals(error)) {
        primaryState = RequestState.FAILED;
        if (errorState != RequestState.RUNNING) {
          errorState = RequestState.RUNNING;
          //开始错误请求
          error.begin();
        }
        return;
      }

      errorState = RequestState.FAILED;

      if (parent != null) {
        parent.onRequestFailed(this);
      }
    }
  }

  @Override
  public RequestCoordinator getRoot() {
    synchronized (requestLock) {
      return parent != null ? parent.getRoot() : this;
    }
  }
}

2.3 封装主图请求和缩略图请求

RequestBuilder.java 
  
 //创建缩略图请求
private Request buildThumbnailRequestRecursive(
      Object requestLock,
      Target<TranscodeType> target,
      RequestListener<TranscodeType> targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      BaseRequestOptions<?> requestOptions,
      Executor callbackExecutor) {
      
    //如果设置缩略请求的建造者
    if (thumbnailBuilder != null) {
      // Recursive case: contains a potentially recursive thumbnail request builder.
      ···
      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);
	···

      ThumbnailRequestCoordinator coordinator =
          new ThumbnailRequestCoordinator(requestLock, parentCoordinator);
      //创建主图请求
      Request fullRequest =
          obtainRequest(
              requestLock,
              target,
              targetListener,
              requestOptions,
              coordinator,
              transitionOptions,
              priority,
              overrideWidth,
              overrideHeight,
              callbackExecutor);
      isThumbnailBuilt = true;
      // Recursively generate thumbnail requests.
      //创建缩略图请求
      Request thumbRequest =
          thumbnailBuilder.buildRequestRecursive(
              requestLock,
              target,
              targetListener,
              coordinator,
              thumbTransitionOptions,
              thumbPriority,
              thumbOverrideWidth,
              thumbOverrideHeight,
              thumbnailBuilder,
              callbackExecutor);
      isThumbnailBuilt = false;
      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(requestLock, parentCoordinator);
      //创建主图请求
      Request fullRequest =
          obtainRequest(
              requestLock,
              target,
              targetListener,
              requestOptions,
              coordinator,
              transitionOptions,
              priority,
              overrideWidth,
              overrideHeight,
              callbackExecutor);
      BaseRequestOptions<?> thumbnailOptions =
          requestOptions.clone().sizeMultiplier(thumbSizeMultiplier);
	//创建缩略图请求
      Request thumbnailRequest =
          obtainRequest(
              requestLock,
              target,
              targetListener,
              thumbnailOptions,
              coordinator,
              transitionOptions,
              getThumbnailPriority(priority),
              overrideWidth,
              overrideHeight,
              callbackExecutor);

      coordinator.setRequests(fullRequest, thumbnailRequest);
      return coordinator;
    } else {
      // Base case: no thumbnail.
      //没有设置缩略图,创建主图请求
      return obtainRequest(
          requestLock,
          target,
          targetListener,
          requestOptions,
          parentCoordinator,
          transitionOptions,
          priority,
          overrideWidth,
          overrideHeight,
          callbackExecutor);
    }
  }

2.4 创建请求

RequestBuilder.java 

private Request obtainRequest(
      Object requestLock,
      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,
        requestLock,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        glideContext.getEngine(),
        transitionOptions.getTransitionFactory(),
        callbackExecutor);
  }
  
 SingleRequest.java
 
  public static <R> SingleRequest<R> obtain(
      Context context,
      GlideContext glideContext,
      Object requestLock,
      Object model,
      Class<R> transcodeClass,
      BaseRequestOptions<?> requestOptions,
      int overrideWidth,
      int overrideHeight,
      Priority priority,
      Target<R> target,
      RequestListener<R> targetListener,
      @Nullable List<RequestListener<R>> requestListeners,
      RequestCoordinator requestCoordinator,
      Engine engine,
      TransitionFactory<? super R> animationFactory,
      Executor callbackExecutor) {
    return new SingleRequest<>(
        context,
        glideContext,
        requestLock,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        engine,
        animationFactory,
        callbackExecutor);
  }
  
  
private SingleRequest(
      Context context,
      GlideContext glideContext,
      @NonNull Object requestLock,
      @Nullable Object model,
      Class<R> transcodeClass,
      BaseRequestOptions<?> requestOptions,
      int overrideWidth,
      int overrideHeight,
      Priority priority,
      Target<R> target,
      @Nullable RequestListener<R> targetListener,
      @Nullable List<RequestListener<R>> requestListeners,
      RequestCoordinator requestCoordinator,
      Engine engine,
      TransitionFactory<? super R> animationFactory,
      Executor callbackExecutor) {
    this.requestLock = requestLock;
    this.context = context;
    this.glideContext = glideContext;
    this.model = model;
    this.transcodeClass = transcodeClass;
    this.requestOptions = requestOptions;
    this.overrideWidth = overrideWidth;
    this.overrideHeight = overrideHeight;
    this.priority = priority;
    this.target = target;
    this.targetListener = targetListener;
    this.requestListeners = requestListeners;
    this.requestCoordinator = requestCoordinator;
    this.engine = engine;
    this.animationFactory = animationFactory;
    this.callbackExecutor = callbackExecutor;
    status = Status.PENDING;

    if (requestOrigin == null && glideContext.isLoggingRequestOriginsEnabled()) {
      requestOrigin = new RuntimeException("Glide request origin trace");
    }
  }

通过静态工厂的方式创建真正的SingleRequest请求

三 处理Target重复请求

如果Target中有相同的图片请求,可以直接请求,有效提高性能

RequestBuilder.java

private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> options,
      Executor callbackExecutor) {
    

	//取出target之前保存的Request
    Request previous = target.getRequest();
    //如果target存储的请求和新创建的请求相等(包括尺寸)并且target的请求没有设置内存缓存并加载过了
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
      // 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.
      //target请不是在请求中
      if (!Preconditions.checkNotNull(previous).isRunning()) {
        // 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);
    //设置target的Request
    target.setRequest(request);
    //跟中Request,并触发请求
    requestManager.track(target, request);

    return target;
  }
  
 private boolean isSkipMemoryCacheWithCompletePreviousRequest(
      BaseRequestOptions<?> options, Request previous) {
    return !options.isMemoryCacheable() && previous.isComplete();
  }

四 发送请求

RequestBuilder.java

private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> options,
      Executor callbackExecutor) {
   ····

    requestManager.clear(target);
    target.setRequest(request);
    //用于触发请求
    requestManager.track(target, request);

    return target;
    
    
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
    targetTracker.track(target);
    requestTracker.runRequest(request);
  }

4.1 跟踪Tartget生命周期

targetTracker是TargetTracker用于跟踪Target生命周期

TargetTracker.java

public final class TargetTracker implements LifecycleListener {
  private final Set<Target<?>> targets =
      Collections.newSetFromMap(new WeakHashMap<Target<?>, Boolean>());

  public void track(@NonNull Target<?> target) {
    targets.add(target);
  }

  public void untrack(@NonNull Target<?> target) {
    targets.remove(target);
  }

  @Override
  public void onStart() {
    for (Target<?> target : Util.getSnapshot(targets)) {
      target.onStart();
    }
  }

  @Override
  public void onStop() {
    for (Target<?> target : Util.getSnapshot(targets)) {
      target.onStop();
    }
  }

  @Override
  public void onDestroy() {
    for (Target<?> target : Util.getSnapshot(targets)) {
      target.onDestroy();
    }
  }

  @NonNull
  public List<Target<?>> getAll() {
    return Util.getSnapshot(targets);
  }

  public void clear() {
    targets.clear();
  }
}

4.2 跟踪Request生命周期

requestTracker是RequestTracker用于跟中Request

RequestTracker.java

public class RequestTracker {
  private static final String TAG = "RequestTracker";
  //跟踪所有的request
  private final Set<Request> requests =
      Collections.newSetFromMap(new WeakHashMap<Request, Boolean>());
  /准备发送的请求
  @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
  private final List<Request> pendingRequests = new ArrayList<>();

  private boolean isPaused;

  /** Starts tracking the given request. */
  public void runRequest(@NonNull Request request) {
  	//添加到请集合中
    requests.add(request);
    if (!isPaused) {
      //如果没有暂停那么开始执行请求
      request.begin();
    } else {
      //如果暂停了加入到待请求集合中
      request.clear();
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Paused, delaying request");
      }
      pendingRequests.add(request);
    }
  }
  ····

4.3 执行请求

request.begin();执行的是SingleRequest的begin()方法

SingleRequest.java


@Override
  public void begin() {
  	//同步锁
    synchronized (requestLock) {
          ···
      //如果加载完成直接调用onResourceReady
      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;
      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));
      }
    }
  }

getPlaceholderDrawable()获取占位符,加载时用于显示的图片

SingleRequest.java

 private Drawable getPlaceholderDrawable() {
    if (placeholderDrawable == null) {
      placeholderDrawable = requestOptions.getPlaceholderDrawable();
      if (placeholderDrawable == null && requestOptions.getPlaceholderId() > 0) {
        placeholderDrawable = loadDrawable(requestOptions.getPlaceholderId());
      }
    }
    return placeholderDrawable;
  }

target.onLoadStarted(getPlaceholderDrawable()),这个target是继承制ViewTarget,所以调用的事ViewTarget的onLoadStarted

ViewTarget.java

public void onLoadStarted(@Nullable Drawable placeholder) {
    super.onLoadStarted(placeholder);
    maybeAddAttachStateListener();
  }
  
private void maybeAddAttachStateListener() {
    if (attachStateListener == null || isAttachStateListenerAdded) {
      return;
    }
    view.addOnAttachStateChangeListener(attachStateListener);
    isAttachStateListenerAdded = true;
  }

给Target添加了一个attach监听,当view attach到View上时会触发回调

ViewTarget.java

attachStateListener =
        new OnAttachStateChangeListener() {
          @Override
          public void onViewAttachedToWindow(View v) {
          //恢复请求
            resumeMyRequest();
          }

          @Override
          public void onViewDetachedFromWindow(View v) {
          //暂停请求
            pauseMyRequest();
          }
        };
        
void resumeMyRequest() {
    Request request = getRequest();
    if (request != null && request.isCleared()) {
      request.begin();
    }
  }
  
void resumeMyRequest() {
    Request request = getRequest();
    if (request != null && request.isCleared()) {
      request.begin();
    }
  }