Glide源碼分析

版本4.9.0android

問題

  • Glide如何實現與生命週期的綁定?
  • Glide如何實現緩存?
  • Glide如何實現圖片壓縮?

Glide如何實現與生命週期的綁定?

建立RequestManger,將其與with()傳入 Activity, Fragment的生命週期綁定,
這樣作的好處是當Activity/Fragment stop/destroy時,RequestManager也會作相應操做,如停掉圖片加載緩存

  • 綁定Application Contextapp

    首先不管with()傳入的是什麼,只要是在子線程中調用,建立的RequestManger與 Application Context綁定,這樣建立的RequestMangager的生命週期與ide

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

    這樣作的目的是防止Activity,Fragment內存泄漏ui

  • Activity與FramgentActivitythis

    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實現了綁定code

  • Fragment
    與Activity的綁定方式相似,orm

    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;
相關文章
相關標籤/搜索