美文网首页
glide 4.10+源码主流程分析

glide 4.10+源码主流程分析

作者: Big_Sweet | 来源:发表于2021-03-08 15:15 被阅读0次

    本文章基于glide4.11.0源码分析主流程

    主流程代码为 Glide.with(activity).load(url).into(target)
    

    .with方法

     @NonNull
      public static RequestManager with(@NonNull FragmentActivity activity) {
        return getRetriever(activity).get(activity);
      }
    

    get方法

     @NonNull
    public RequestManager get(@NonNull FragmentActivity activity) {
      if (Util.isOnBackgroundThread()) {
        return get(activity.getApplicationContext());
      } else {
        assertNotDestroyed(activity);
        FragmentManager fm = activity.getSupportFragmentManager();
        return supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
      }
    }
    

    一般来说都是在主线程,所以看下面的supportFragmentGet

     @NonNull
      private RequestManager supportFragmentGet(
          @NonNull Context context,
          @NonNull FragmentManager fm,
          @Nullable Fragment parentHint,
          boolean isParentVisible) {
        SupportRequestManagerFragment current =
            getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
        **省略若干代码
        return requestManager;
      }
    

    因为只看我觉得重要的主流程,所以一些干扰代码直接省去了
    getSupportRequestManagerFragment方法

    @NonNull
    private SupportRequestManagerFragment getSupportRequestManagerFragment(
        @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
      SupportRequestManagerFragment current =
          (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
          fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
          handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
        }
      }
      return current;
    }
    

    总结一下with方法做了什么
    .with传入了一个上下文,glide通过这个上下文,创建了一个requestmanager和一个空的fragment,将fragment添加到activity中,将requestmanager和fragment进行绑定。这样这个requestmanager就拥有生命周期了
    .load 只是进行了一些参数的赋值,获取到了一个requestbuilder
    最重要的是into方法
    .into方法

     @NonNull
    public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
      Util.assertMainThread();
      return into(
          glideContext.buildImageViewTarget(view, transcodeClass),
          /*targetListener=*/ null,
          requestOptions,
          Executors.mainThreadExecutor());
    }
    

    注意buildimageviewtarget返回的是DrawableImageViewTarget
    可以自行点进去看
    继续看into

    private <Y extends Target<TranscodeType>> Y into(
        @NonNull Y target,
        @Nullable RequestListener<TranscodeType> targetListener,
        BaseRequestOptions<?> options,
        Executor callbackExecutor) {
      Request request = buildRequest(target, targetListener, options, callbackExecutor);
        Request previous = target.getRequest();
      if (request.isEquivalentTo(previous)
          && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
        if (!Preconditions.checkNotNull(previous).isRunning()) {
          previous.begin();
        }
        return target;
      }
    }
    
    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);
    }
    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) {
    
      Request mainRequest =
          buildThumbnailRequestRecursive(
              requestLock,
              target,
              targetListener,
              parentCoordinator,
              transitionOptions,
              priority,
              overrideWidth,
              overrideHeight,
              requestOptions,
              callbackExecutor);
    }
    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) {
     
        Request fullRequest =
            obtainRequest(
                requestLock,
                target,
                targetListener,
                requestOptions,
                coordinator,
                transitionOptions,
                priority,
                overrideWidth,
                overrideHeight,
                callbackExecutor);
       
    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方法里面
    在into的时候下面有一句话 previous.begin();
    也就是获取到了这个request之后会执行begin方法,那么直接去看SingleRequest的begin方法

     @Override
      public void begin() {
        synchronized (requestLock) {
          if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
            onSizeReady(overrideWidth, overrideHeight);
          } else {
            target.getSize(this);
          }
    

    target.getsize最后也会走到onSizeReady方法里面前面我们已经得到了target是DrawableImageViewTarget可以自行去看
    接下来看onSizeReady位于singlerequest方法中

    @Override
      public void onSizeReady(int width, int height) {
        stateVerifier.throwIfRecycled();
        synchronized (requestLock) {
          loadStatus =
              engine.load(
                  glideContext,
                  model,
                  requestOptions.getSignature(),
                  this.width,
                  this.height,
                  requestOptions.getResourceClass(),
                  transcodeClass,
                  priority,
                  requestOptions.getDiskCacheStrategy(),
                  requestOptions.getTransformations(),
                  requestOptions.isTransformationRequired(),
                  requestOptions.isScaleOnlyOrNoTransform(),
                  requestOptions.getOptions(),
                  requestOptions.isMemoryCacheable(),
                  requestOptions.getUseUnlimitedSourceGeneratorsPool(),
                  requestOptions.getUseAnimationPool(),
                  requestOptions.getOnlyRetrieveFromCache(),
                  this,
                  callbackExecutor);
    

    engine.load方法

    public <R> LoadStatus load(
          GlideContext glideContext,
          Object model,
          Key signature,
          int width,
          int height,
          Class<?> resourceClass,
          Class<R> transcodeClass,
          Priority priority,
          DiskCacheStrategy diskCacheStrategy,
          Map<Class<?>, Transformation<?>> transformations,
          boolean isTransformationRequired,
          boolean isScaleOnlyOrNoTransform,
          Options options,
          boolean isMemoryCacheable,
          boolean useUnlimitedSourceExecutorPool,
          boolean useAnimationPool,
          boolean onlyRetrieveFromCache,
          ResourceCallback cb,
          Executor callbackExecutor) {
        long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
    
    **缓存代码都删除了,第一次加载肯定是没有缓存的所以memoryResource==null
          if (memoryResource == null) {
            return waitForExistingOrStartNewJob(
                glideContext,
                model,
                signature,
                width,
                height,
                resourceClass,
                transcodeClass,
                priority,
                diskCacheStrategy,
                transformations,
                isTransformationRequired,
                isScaleOnlyOrNoTransform,
                options,
                isMemoryCacheable,
                useUnlimitedSourceExecutorPool,
                useAnimationPool,
                onlyRetrieveFromCache,
                cb,
                callbackExecutor,
                key,
                startTime);
          }
        }
        return null;
      }
    
    
    private <R> LoadStatus waitForExistingOrStartNewJob(
          GlideContext glideContext,
          Object model,
          Key signature,
          int width,
          int height,
          Class<?> resourceClass,
          Class<R> transcodeClass,
          Priority priority,
          DiskCacheStrategy diskCacheStrategy,
          Map<Class<?>, Transformation<?>> transformations,
          boolean isTransformationRequired,
          boolean isScaleOnlyOrNoTransform,
          Options options,
          boolean isMemoryCacheable,
          boolean useUnlimitedSourceExecutorPool,
          boolean useAnimationPool,
          boolean onlyRetrieveFromCache,
          ResourceCallback cb,
          Executor callbackExecutor,
          EngineKey key,
          long startTime) {
        EngineJob<R> engineJob =
            engineJobFactory.build(
                key,
                isMemoryCacheable,
                useUnlimitedSourceExecutorPool,
                useAnimationPool,
                onlyRetrieveFromCache);
    
        DecodeJob<R> decodeJob =
            decodeJobFactory.build(
                glideContext,
                model,
                key,
                signature,
                width,
                height,
                resourceClass,
                transcodeClass,
                priority,
                diskCacheStrategy,
                transformations,
                isTransformationRequired,
                isScaleOnlyOrNoTransform,
                onlyRetrieveFromCache,
                options,
                engineJob);
    
        jobs.put(key, engineJob);
    
        engineJob.addCallback(cb, callbackExecutor);
        engineJob.start(decodeJob);
      }
      
    

    engineJob.start(decodeJob);启动engineJob
    那么直接去看engineJob的run方法
    enginejob是一个runnable

    @Override
      public void run() {
          runWrapped();  
      }
     private void runWrapped() {
        switch (runReason) {
          case INITIALIZE:
            stage = getNextStage(Stage.INITIALIZE);
            currentGenerator = getNextGenerator();
            runGenerators();
            break;
          case SWITCH_TO_SOURCE_SERVICE:
            runGenerators();
            break;
          case DECODE_DATA:
            decodeFromRetrievedData();
            break;
          default:
            throw new IllegalStateException("Unrecognized run reason: " + runReason);
        }
      }
      
    

    默认我们的runReason就是INITIALIZE
    所以直接看runGenerators

    private void runGenerators() {
        while (!isCancelled
            && currentGenerator != null
            && !(isStarted = currentGenerator.startNext())) {
          stage = getNextStage(stage);
          currentGenerator = getNextGenerator();
      }
    

    这里可以看到getNextGenerator获取到的是SourceGenerator

    
    private DataFetcherGenerator getNextGenerator() {
      switch (stage) {
        case RESOURCE_CACHE:
          return new ResourceCacheGenerator(decodeHelper, this);
        case DATA_CACHE:
          return new DataCacheGenerator(decodeHelper, this);
        case SOURCE:
          return new SourceGenerator(decodeHelper, this);
        case FINISHED:
          return null;
        default:
          throw new IllegalStateException("Unrecognized stage: " + stage);
      }
    }
    

    上面的代码就是获取获取一个Generator并且执行,
    那么在第一次加载没有缓存的情况下获取到的就是SourceGenerator
    那我们看SourceGenerator的startNext方法

    @Override
      public boolean startNext() {
       
        while (!started && hasNextModelLoader()) {
          loadData = helper.getLoadData().get(loadDataListIndex++);
          if (loadData != null
              && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
                  || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
            started = true;
            startNextLoad(loadData);
          }
        }
        return started;
      }
    
    
    private void startNextLoad(final LoadData<?> toStart) {
        loadData.fetcher.loadData(
            helper.getPriority(),
            new DataCallback<Object>() {
              @Override
              public void onDataReady(@Nullable Object data) {
                if (isCurrentRequest(toStart)) {
                  onDataReadyInternal(toStart, data);
                }
              }
    
              @Override
              public void onLoadFailed(@NonNull Exception e) {
                if (isCurrentRequest(toStart)) {
                  onLoadFailedInternal(toStart, e);
                }
              }
            });
      }
    

    调用fetch的loadData方法
    因为我们这里加载的是网络图片所以获取到的fetch是HttpUrlFetcher
    HttpUrlFetcher的loadData方法
    接下来看

     @Override
      public void loadData(
          @NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
     
          InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
          callback.onDataReady(result);
       
      }
    private InputStream loadDataWithRedirects(
          URL url, int redirects, URL lastUrl, Map<String, String> headers) throws IOException {
        urlConnection = connectionFactory.build(url);
        for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
          urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
        }
        urlConnection.setConnectTimeout(timeout);
        urlConnection.setReadTimeout(timeout);
        urlConnection.setUseCaches(false);
        urlConnection.setDoInput(true);
        urlConnection.setInstanceFollowRedirects(false);
        urlConnection.connect();
        stream = urlConnection.getInputStream();
        }
    

    这里出现了熟悉的网络代码将url变成了一个inputstream
    获取到了inputstream了之后 这个流是怎么转换为图片设置到我们的target上面的呢,继续往下看
    callback.onDataReady(result);
    这个callback是前面loaddata的时候new出来的所以回调直接在SourceGenerator里面

    private void startNextLoad(final LoadData<?> toStart) {
        loadData.fetcher.loadData(
            helper.getPriority(),
            new DataCallback<Object>() {
              @Override
              public void onDataReady(@Nullable Object data) {
                if (isCurrentRequest(toStart)) {
                  onDataReadyInternal(toStart, data);
                }
              }
    
              @Override
              public void onLoadFailed(@NonNull Exception e) {
                if (isCurrentRequest(toStart)) {
                  onLoadFailedInternal(toStart, e);
                }
              }
            });
      }
    
    
      @SuppressWarnings("WeakerAccess")
      @Synthetic
      void onDataReadyInternal(LoadData<?> loadData, Object data) {
          cb.onDataFetcherReady(
              loadData.sourceKey,
              data,
              loadData.fetcher,
              loadData.fetcher.getDataSource(),
              originalKey);
      }
    

    走到了cb.onDataFetcherReady,cb是在哪里设置的呢
    在DecodeJob.getNextGenerator的时候设置了cb,所以我们看DecodeJob的onDataFetcherReady方法

    @Override
      public void onDataFetcherReady(
          Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) {
          deFromRetrievedData();
      }
    
      private void decodeFromRetrievedData() {
          resource = decodeFromData(currentFetcher, currentData, currentDataSource);
          if (resource != null) {
          notifyEncodeAndRelease(resource, currentDataSource);
        } else {
          runGenerators();
        }
      }
      
      我们先看解码图片的代码,解码完成后会走notifyEncodeAndRelease
      
      private <Data> Resource<R> decodeFromData(
          DataFetcher<?> fetcher, Data data, DataSource dataSource) throws GlideException {
       
          Resource<R> result = decodeFromFetcher(data, dataSource);
    
      }
      
     @SuppressWarnings("unchecked")
      private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
          throws GlideException {
        LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
        return runLoadPath(data, dataSource, path);
      }
    注意这里的decodeHelper.getLoadPath方法,在下面解码图片获取decoder的时候,decode是在这里初始化的
    
      private <Data, ResourceType> Resource<R> runLoadPath(
          Data data, DataSource dataSource, LoadPath<Data, ResourceType, R> path)
          throws GlideException {
       
          return path.load(
              rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
     
      }
    
     public Resource<Transcode> load(
          DataRewinder<Data> rewinder,
          @NonNull Options options,
          int width,
          int height,
          DecodePath.DecodeCallback<ResourceType> decodeCallback)
          throws GlideException {
      
          return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables);
      
      }
    
    private Resource<Transcode> loadWithExceptionList(
          DataRewinder<Data> rewinder,
          @NonNull Options options,
          int width,
          int height,
          DecodePath.DecodeCallback<ResourceType> decodeCallback,
          List<Throwable> exceptions)
          throws GlideException {
      
            result = path.decode(rewinder, width, height, options, decodeCallback);
      
        return result;
      }
      
      
      public Resource<Transcode> decode(
          DataRewinder<DataType> rewinder,
          int width,
          int height,
          @NonNull Options options,
          DecodeCallback<ResourceType> callback)
          throws GlideException {
        Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
        Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
        return transcoder.transcode(transformed, options);
      }
    
    
     @NonNull
      private Resource<ResourceType> decodeResource(
       
        try {
          return decodeResourceWithList(rewinder, width, height, options, exceptions);
        } finally {
         
        }
      }
      
    @NonNull
      private Resource<ResourceType> decodeResourceWithList(
       
            if (decoder.handles(data, options)) {
              data = rewinder.rewindAndGet();
              result = decoder.decode(data, width, height, options);
        
      }
      
    这里讲一下这个decoder是哪里来的在前面我标记了decodeHelper.getLoadPath这个方法
    <Data> LoadPath<Data, ?, Transcode> getLoadPath(Class<Data> dataClass) {
        return glideContext.getRegistry().getLoadPath(dataClass, resourceClass, transcodeClass);
      }
      这个方法里面初始化了decoder
    
      @Nullable
      public <Data, TResource, Transcode> LoadPath<Data, TResource, Transcode> getLoadPath(
          @NonNull Class<Data> dataClass,
          @NonNull Class<TResource> resourceClass,
          @NonNull Class<Transcode> transcodeClass) {
          List<DecodePath<Data, TResource, Transcode>> decodePaths =
              getDecodePaths(dataClass, resourceClass, transcodeClass);
         
        return result;
      }
    
    
    @NonNull
      private <Data, TResource, Transcode> List<DecodePath<Data, TResource, Transcode>> getDecodePaths(
          @NonNull Class<Data> dataClass,
          @NonNull Class<TResource> resourceClass,
          @NonNull Class<Transcode> transcodeClass) {
       
            List<ResourceDecoder<Data, TResource>> decoders =
                decoderRegistry.getDecoders(dataClass, registeredResourceClass);
        
      }
     
      public synchronized <T, R> List<ResourceDecoder<T, R>> getDecoders(
          @NonNull Class<T> dataClass, @NonNull Class<R> resourceClass) {
        List<ResourceDecoder<T, R>> result = new ArrayList<>();
        for (String bucket : bucketPriorityList) {
          List<Entry<?, ?>> entries = decoders.get(bucket);
          if (entries == null) {
            continue;
          }
          for (Entry<?, ?> entry : entries) {
            if (entry.handles(dataClass, resourceClass)) {
              result.add((ResourceDecoder<T, R>) entry.decoder);
            }
          }
        }
        return result;
      }
      
    这里可以看到decoder都是在bucketPriorityList中获取到的而bucketPriorityList是通过
    setBucketPriorityList方法设置的
    如下在registry类构建的时候设置了3个一个gif一个bitmap一个gitmapdrawable
     public Registry() {
        this.modelLoaderRegistry = new ModelLoaderRegistry(throwableListPool);
        this.encoderRegistry = new EncoderRegistry();
        this.decoderRegistry = new ResourceDecoderRegistry();
        this.resourceEncoderRegistry = new ResourceEncoderRegistry();
        this.dataRewinderRegistry = new DataRewinderRegistry();
        this.transcoderRegistry = new TranscoderRegistry();
        this.imageHeaderParserRegistry = new ImageHeaderParserRegistry();
        setResourceDecoderBucketPriorityList(
            Arrays.asList(BUCKET_GIF, BUCKET_BITMAP, BUCKET_BITMAP_DRAWABLE));
      }
    
    而BUCKET_BITMAP_DRAWABLE
    对应的是
    .append(
                Registry.BUCKET_BITMAP_DRAWABLE,
                ByteBuffer.class,
                BitmapDrawable.class,
                new BitmapDrawableDecoder<>(resources, byteBufferBitmapDecoder))
            .append(
                Registry.BUCKET_BITMAP_DRAWABLE,
                InputStream.class,
                BitmapDrawable.class,
                new BitmapDrawableDecoder<>(resources, streamBitmapDecoder))
            .append(
                Registry.BUCKET_BITMAP_DRAWABLE,
                ParcelFileDescriptor.class,
                BitmapDrawable.class,
                new BitmapDrawableDecoder<>(resources, parcelFileDescriptorVideoDecoder))
    streamBitmapDecoder = new InputStreamBitmapImageDecoderResourceDecoder();
    所以很明显我们的是inputstream所以最后只需要看InputStreamBitmapImageDecoderResourceDecoder的decoder方法
    

    InputStreamBitmapImageDecoderResourceDecoder的
    decode方法

    @Override
      protected Resource<Bitmap> decode(
          Source source,
          int requestedResourceWidth,
          int requestedResourceHeight,
          OnHeaderDecodedListener listener)
          throws IOException {
        Bitmap result = ImageDecoder.decodeBitmap(source, listener);
        return new BitmapResource(result, bitmapPool);
      }
    

    返回一个ResourceBitmap
    然后回到解码的地方,解码成功后

    private void decodeFromRetrievedData() {
      
          resource = decodeFromData(currentFetcher, currentData, currentDataSource);
       if (resource != null) {
          notifyEncodeAndRelease(resource, currentDataSource);
        } else {
          runGenerators();
        }
      }
    

    解码完成后调用

    private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
      
        notifyComplete(result, dataSource);
    
      }
    private void notifyComplete(Resource<R> resource, DataSource dataSource) {
        setNotifiedOrThrow();
        callback.onResourceReady(resource, dataSource);
      }
      
    

    callback是EngineJob可以回退自行查看
    接下来看EngineJob的onResourceReady

    
      @Override
      public void onResourceReady(Resource<R> resource, DataSource dataSource) {
        synchronized (this) {
          this.resource = resource;
          this.dataSource = dataSource;
        }
        notifyCallbacksOfResult();
      }
    
    
     @Synthetic
      void notifyCallbacksOfResult() {
      
        for (final ResourceCallbackAndExecutor entry : copy) {
          entry.executor.execute(new CallResourceReady(entry.cb));
        }
      }
      CallResourceReady的run方法
    
     @Override
        public void run() {
            callCallbackOnResourceReady(cb);
          
        }
     
      void callCallbackOnResourceReady(ResourceCallback cb) {
      
          cb.onResourceReady(engineResource, dataSource);
      
      }
      这个cb是SingleRequest有兴趣的可以跟着回退一步一步看,很容易就能找到
      
    @SuppressWarnings("unchecked")
      @Override
      public void onResourceReady(Resource<?> resource, DataSource dataSource) {
        stateVerifier.throwIfRecycled();
      
            onResourceReady((Resource<R>) resource, (R) received, dataSource);
          }
      }
    
    @GuardedBy("requestLock")
      private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
            target.onResourceReady(result, animation);、
      }
    
    

    前面我们已经知道target是DrawableImageViewTarget
    那么去看一下onResourceReady
    在DrawableImageViewTarget的父类ImageViewTarget中

      @Override
      public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
        if (transition == null || !transition.transition(resource, this)) {
          setResourceInternal(resource);
        } else {
          maybeUpdateAnimatable(resource);
        }
      }
    private void setResourceInternal(@Nullable Z resource) {
        // Order matters here. Set the resource first to make sure that the Drawable has a valid and
        // non-null Callback before starting it.
        setResource(resource);
        maybeUpdateAnimatable(resource);
      }
    
    protected abstract void setResource(@Nullable Z resource);
    
    
    

    回调子类的setResource方法我们来看下DrawableImageViewTarget的setResource

    @Override
      protected void setResource(@Nullable Drawable resource) {
        view.setImageDrawable(resource);
      }
    

    好了到这里主流程就分析完了,看了2-3天才梳理完这么简单的一句话
    Glide.with(activity).load(url).into(target)
    里面很多的callback都是设置的this,所以在找callback的时候要稍微注意一下,整个看完给我的感觉就是真的很复杂,是一个从外到里,在由里面回调出来的一个过程。
    下一篇开始分析glide缓存的源码

    相关文章

      网友评论

          本文标题:glide 4.10+源码主流程分析

          本文链接:https://www.haomeiwen.com/subject/xtipqltx.html