Glide源码分析

版本4.9.0

问题

  • Glide如何实现与生命周期的绑定?
  • Glide如何实现缓存?
  • Glide如何实现图片压缩?

Glide如何实现与生命周期的绑定?

创建RequestManger,将其与with()传入 Activity, Fragment的生命周期绑定,
这样做的好处是当Activity/Fragment stop/destroy时,RequestManager也会做相应操作,如停掉图片加载

  • 绑定Application Context

    首先无论with()传入的是什么,只要是在子线程中调用,创建的RequestManger与 Application Context绑定,这样创建的RequestMangager的生命周期与

    if (Util.isOnBackgroundThread()) {
            return get(fragment.getActivity().getApplicationContext());
         } else {
          ... ...
        }

    这样做的目的是防止Activity,Fragment内存泄漏

  • Activity与FramgentActivity

    class RequestManagerFragment {
          ... ...
          private final ActivityFragmentLifecycle lifecycle;
         
          @Override
          public void onStart() {
            super.onStart();
            lifecycle.onStart();
          }
          @Override
          public void onStop() {
            super.onStop();
            lifecycle.onStop();
          }
    
          @Override
          public void onDestroy() {
            super.onDestroy();
            lifecycle.onDestroy();
            unregisterFragmentWithRoot();
          }
          ... ...
        }
    class ActivityFragmentLifecycle implements Lifecycle {
          @Override
          public void addListener(@NonNull LifecycleListener listener) {
            lifecycleListeners.add(listener);
    
            if (isDestroyed) {
              listener.onDestroy();
            } else if (isStarted) {
              listener.onStart();
            } else {
              listener.onStop();
            }
          }
          void onStart() {
            isStarted = true;
            for (LifecycleListener lifecycleListener :             Util.getSnapshot(lifecycleListeners)) {
              lifecycleListener.onStart();
            }
          }
    
          void onStop() {
            isStarted = false;
            for (LifecycleListener lifecycleListener :     Util.getSnapshot(lifecycleListeners)) {
              lifecycleListener.onStop();
            }
          }
    
          void onDestroy() {
            isDestroyed = true;
            for (LifecycleListener lifecycleListener :     Util.getSnapshot(lifecycleListeners)) {
              lifecycleListener.onDestroy();
            }
          }
        }
    RequestManagerFragment current = getRequestManagerFragment(fm,         
                     parentHint, isParentVisible);
        RequestManager requestManager = current.getRequestManager();
        if (requestManager == null) {
          // TODO(b/27524013): Factor out this Glide.get() call.
          Glide glide = Glide.get(context);
          requestManager = factory.build(glide, current.getGlideLifecycle(),               current.getRequestManagerTreeNode(), context);
          current.setRequestManager(requestManager);
        }

    RequestManagerFragment中创建了并对外提供ActivityFragmentLifecycle对象,
    创建RequestManager时,传入ActivityFragmentLifecycle对象

    RequestManager(
          Glide glide,
          Lifecycle lifecycle,
          RequestManagerTreeNode treeNode,
          RequestTracker requestTracker,
          ConnectivityMonitorFactory factory,
          Context context) {
    
            ... ...      
            lifecycle.addListener(this); 
            ... ...
        }
    
        @Override
        public synchronized void onStart() {
          resumeRequests();
          targetTracker.onStart();
        }
        @Override
        public synchronized void onStop() {
          pauseRequests();
          targetTracker.onStop();
        }
        @Override
        public synchronized void onDestroy() {
          targetTracker.onDestroy();
          for (Target<?> target : targetTracker.getAll()) {
            clear(target);
          }
          targetTracker.clear();
          requestTracker.clearRequests();
          lifecycle.removeListener(this);
          lifecycle.removeListener(connectivityMonitor);
          mainHandler.removeCallbacks(addSelfToLifecycle);
          glide.unregisterRequestManager(this);
        }

    这样RequestManger.onStart(),onStop(),onDestroy()与Activity的生命周期通过Activity绑定的空Fragment实现了绑定

  • Fragment
    与Activity的绑定方式类似,

    FragmentManager fm = fragment.getChildFragmentManager();

    将RequestManger.onStart(),onStop(),onDestroy()与Fragment的生命周期通过Fragment绑定的空Fragment实现的绑定

  • View
    通过View可以获取它所在的Activity 或 Fragment

    Activity activity = findActivity(view.getContext());
    
      @Nullable
      private Activity findActivity(@NonNull Context context) {
        if (context instanceof Activity) {
          return (Activity) context;
        } else if (context instanceof ContextWrapper) {
          return findActivity(((ContextWrapper) context).getBaseContext());
        } else {
          return null;
        }
      }
      
      @Nullable
      private Fragment findSupportFragment(@NonNull View target, @NonNull   
            FragmentActivity activity) {
            
        tempViewToSupportFragment.clear();
        findAllSupportFragmentsWithViews(
            activity.getSupportFragmentManager().getFragments(), tempViewToSupportFragment);
        Fragment result = null;
        View activityRoot = activity.findViewById(android.R.id.content);
        View current = target;
        while (!current.equals(activityRoot)) {
          result = tempViewToSupportFragment.get(current);
          if (result != null) {
            break;
          }
          if (current.getParent() instanceof View) {
            current = (View) current.getParent();
          } else {
            break;
          }
        }
    
        tempViewToSupportFragment.clear();
        return result;
      }
  • Context
    通过Context获取Activity or FragmentActivity or Application Context

    if (context == null) {
          throw new IllegalArgumentException("You cannot start a load on a   nullContext");
        } else if (Util.isOnMainThread() && !(context instanceof Application)){
          if (context instanceof FragmentActivity) {
            return get((FragmentActivity) context);
          } else if (context instanceof Activity) {
            return get((Activity) context);
          } else if (context instanceof ContextWrapper) {
            return get(((ContextWrapper) context).getBaseContext());
          }
        }
        return getApplicationManager(context);

Glide如何实现缓存?

  • 提供了两个内存缓存,分别存储强弱引用
    弱引用的缓存: 存放正在使用的
    强引用的缓存: 存放没有使用的

    Map<Key, ResourceWeakReference> activeEngineResources//在
        private final Map<T, Y> cache = new LinkedHashMap<>(100, 0.75f, true);//在LruCache类中

    查找内存缓存,

    1.先从弱引用的缓存查,
    2.没有再从强引用的缓存查,查到后从强引用缓存中移除,加入到弱引用的缓存

    Engine.load()方法

    EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
        if (active != null) {
          cb.onResourceReady(active, DataSource.MEMORY_CACHE);
          if (VERBOSE_IS_LOGGABLE) {
            logWithTimeAndKey("Loaded resource from active resources", startTime, key);
          }
          return null;
        }
        EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);

    Engine.loadFromCache()方法

    private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) {
        if (!isMemoryCacheable) {
          return null;
        }
    
        EngineResource<?> cached = getEngineResourceFromCache(key); //
        if (cached != null) {
          cached.acquire();
          activeResources.activate(key, cached);
        }
        return cached;
      }
      
      private EngineResource<?> getEngineResourceFromCache(Key key) {
        Resource<?> cached = cache.remove(key);
        final EngineResource<?> result;
        if (cached == null) {
          result = null;
        } else if (cached instanceof EngineResource) {
          // Save an object allocation if we've cached an EngineResource (the typical case).
          result = (EngineResource<?>) cached;
        } else {
          result = new EngineResource<>(cached, true /*isMemoryCacheable*/, true /*isRecyclable*/);
        }
        return result;
      }

Glide如何实现图片压缩?

Glide实现的等比压缩,保持原图长宽比例,主要是通过原图宽高和预设的宽高设置 BitmapFactory.Options.inSampleSize

float widthPercentage = requestedWidth / (float) sourceWidth;
    float heightPercentage = requestedHeight / (float) sourceHeight;
    exactScaleFactor = Math.min(widthPercentage, heightPercentage);
    int outWidth = round(exactScaleFactor * sourceWidth);
    int outHeight = round(exactScaleFactor * sourceHeight);

    int widthScaleFactor = sourceWidth / outWidth;
    int heightScaleFactor = sourceHeight / outHeight;

    int scaleFactor = rounding == SampleSizeRounding.MEMORY
        ? Math.max(widthScaleFactor, heightScaleFactor)
        : Math.min(widthScaleFactor, heightScaleFactor);
    
    int powerOfTwoSampleSize;
    // BitmapFactory does not support downsampling wbmp files on platforms <= M. See b/27305903.
    if (Build.VERSION.SDK_INT <= 23
        && NO_DOWNSAMPLE_PRE_N_MIME_TYPES.contains(options.outMimeType)) {
      powerOfTwoSampleSize = 1;
    } else {
      powerOfTwoSampleSize = Math.max(1, Integer.highestOneBit(scaleFactor));
      if (rounding == SampleSizeRounding.MEMORY
          && powerOfTwoSampleSize < (1.f / exactScaleFactor)) {
        powerOfTwoSampleSize = powerOfTwoSampleSize << 1;
      }
    }
    options.inSampleSize = powerOfTwoSampleSize;

相关推荐