Android-Glide详解

目录

一,介绍

二,使用

三,源码分析思路

四,with源码分析

五,模拟Glide生命周期管理


一,介绍

Glide目前是安卓最主流的加载图片的框架,也是源码最为复杂的框架之一。 要想完完全全吃透Glide的源码,可能需要半年甚至更多的时间。

但是如果分析过Glide的源码,不仅对我们的架构能力有很大提高,也会对面试中的关于Glide的问题知其然更知其所以然。

Glide的精髓,在于它的生命周期的管理和缓存策略。

二,使用

Glide的使用及其简单

java 复制代码
 // 项目的build.gradle添加依赖
    implementation 'com.github.bumptech.glide:glide:4.11.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'

在清单文件添加网络权限:

java 复制代码
 <uses-permission android:name="android.permission.INTERNET"/>

布局文件很简单就一个imageview:

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
         />

</androidx.constraintlayout.widget.ConstraintLayout>

使用:

Kotlin 复制代码
class MainActivity : AppCompatActivity() {
    //图片url
    private val url ="https://q7.itc.cn/q_70/images03/20240714/93ce0113753a4ff4b5f4e48f27ed3739.jpeg"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val iv =findViewById<ImageView>(R.id.iv)
        Glide.with(this).load(url).into(iv)

    }
}

效果:

三,源码分析思路

Glide的源码分析,我们可以从使用角度,拆分为三部分去分析。

java 复制代码
class MainActivity : AppCompatActivity() {
    //图片url
    private val url ="https://q7.itc.cn/q_70/images03/20240714/93ce0113753a4ff4b5f4e48f27ed3739.jpeg"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val iv =findViewById<ImageView>(R.id.iv)
        //第一步 调用with  得到RequestManager
        val requestManager:RequestManager = Glide.with(this)
       
        //第二步 RequestManager调用load 得到requestBulider
        val requestBulider:RequestBuilder<Drawable> =requestManager.load(url)
        
        //第三步 requestBulider调用into
        requestBulider.into(iv)
    }
}

这样拆分的话,思路会比较清晰。

四,with源码分析

首先我们看一下with的源码:

java 复制代码
@NonNull
public static RequestManager with(@NonNull Context context) {
  return getRetriever(context).get(context);
}

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

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

@NonNull
public static RequestManager with(@NonNull Fragment fragment) {
  return getRetriever(fragment.getContext()).get(fragment);
}

@SuppressWarnings("deprecation")
@Deprecated
@NonNull
public static RequestManager with(@NonNull android.app.Fragment fragment) {
  return getRetriever(fragment.getActivity()).get(fragment);
}

@NonNull
public static RequestManager with(@NonNull View view) {
  return getRetriever(view.getContext()).get(view);
}

它可以接受的参数类型很多,确保多种场景下的使用

然后继续往下看getRetriever这个函数:

java 复制代码
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
  // Context could be null for other reasons (ie the user passes in null), but in practice it will
  // only occur due to errors with the Fragment lifecycle.
  Preconditions.checkNotNull(
      context,
      "You cannot start a load on a not yet attached View or a Fragment where getActivity() "
          + "returns null (which usually occurs when getActivity() is called before the Fragment "
          + "is attached or after the Fragment is destroyed).");
  return Glide.get(context).getRequestManagerRetriever();
}

判空不用看,直接看get(context)这个函数:

java 复制代码
@NonNull
public static Glide get(@NonNull Context context) {
  if (glide == null) {
    GeneratedAppGlideModule annotationGeneratedModule =
        getAnnotationGeneratedGlideModules(context.getApplicationContext());
    synchronized (Glide.class) {
      if (glide == null) {
        checkAndInitializeGlide(context, annotationGeneratedModule);
      }
    }
  }
  return glide;
}

这个就是我们熟悉的双重检测单例模式,不了解的可以参考文章:Android 设计模式--单例模式_android开发饿汉单例-CSDN博客

然后我们看看 checkAndInitializeGlide(context, annotationGeneratedModule):

java 复制代码
@GuardedBy("Glide.class")
private static void checkAndInitializeGlide(
    @NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
  // In the thread running initGlide(), one or more classes may call Glide.get(context).
  // Without this check, those calls could trigger infinite recursion.
  if (isInitializing) {
    throw new IllegalStateException(
        "You cannot call Glide.get() in registerComponents(),"
            + " use the provided Glide instance instead");
  }
  isInitializing = true;
  initializeGlide(context, generatedAppGlideModule);
  isInitializing = false;
}

这里好像没有什么具体的信息,我们接着往下看initializeGlide(context,generatedAppGlideModule)这个函数:

java 复制代码
@GuardedBy("Glide.class")
private static void initializeGlide(
    @NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
  initializeGlide(context, new GlideBuilder(), generatedAppGlideModule);
}

好的,依然继续往下看initializeGlide(context, new GlideBuilder(), generatedAppGlideModule)

java 复制代码
@GuardedBy("Glide.class")
@SuppressWarnings("deprecation")
private static void initializeGlide(
    @NonNull Context context,
    @NonNull GlideBuilder builder,
    @Nullable GeneratedAppGlideModule annotationGeneratedModule) {
    //获取应用级别的上下文
  Context applicationContext = context.getApplicationContext();
  List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
  if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
    manifestModules = new ManifestParser(applicationContext).parse();
  }
  if (annotationGeneratedModule != null
      && !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
    Set<Class<?>> excludedModuleClasses = annotationGeneratedModule.getExcludedModuleClasses();
    Iterator<com.bumptech.glide.module.GlideModule> iterator = manifestModules.iterator();
    while (iterator.hasNext()) {
      com.bumptech.glide.module.GlideModule current = iterator.next();
      if (!excludedModuleClasses.contains(current.getClass())) {
        continue;
      }
      if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);
      }
      iterator.remove();
    }
  }
  if (Log.isLoggable(TAG, Log.DEBUG)) {
    for (com.bumptech.glide.module.GlideModule glideModule : manifestModules) {
      Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
    }
  }
//通过注解生成的代码拿到 RequestManagerFactory
  RequestManagerRetriever.RequestManagerFactory factory =
      annotationGeneratedModule != null
          ? annotationGeneratedModule.getRequestManagerFactory()
          : null;
//将拿到的工厂添加到 GlideBuilder
  builder.setRequestManagerFactory(factory);
  for (com.bumptech.glide.module.GlideModule module : manifestModules) {
    module.applyOptions(applicationContext, builder);
  }
  if (annotationGeneratedModule != null) {
    annotationGeneratedModule.applyOptions(applicationContext, builder);
  }
//通过 Builder 建造者模式,构建出 Glide 实例对象
  Glide glide = builder.build(applicationContext);
//注册组件回调
  for (com.bumptech.glide.module.GlideModule module : manifestModules) {
    try {
      module.registerComponents(applicationContext, glide, glide.registry);
    } catch (AbstractMethodError e) {
      throw new IllegalStateException(
          "Attempting to register a Glide v3 module. If you see this, you or one of your"
              + " dependencies may be including Glide v3 even though you're using Glide v4."
              + " You'll need to find and remove (or update) the offending dependency."
              + " The v3 module name is: "
              + module.getClass().getName(),
          e);
    }
  }
  if (annotationGeneratedModule != null) {
    annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
  }
  applicationContext.registerComponentCallbacks(glide);
//将构建出来的 glide 赋值给 Glide 的静态变量
  Glide.glide = glide;
}

这个函数里面的信息量是非常大的,主要是进行了一系列的初始化操作,通过 Builder 建造者模式,构建出 Glide 实例对象,接着我们看看builder模式进行了哪些构建:

java 复制代码
@NonNull
Glide build(@NonNull Context context) {
//网络请求的线程池
  if (sourceExecutor == null) {
    sourceExecutor = GlideExecutor.newSourceExecutor();
  }
//本地磁盘缓存的线程池
  if (diskCacheExecutor == null) {
    diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
  }
//加载图片动画的一个线程池
  if (animationExecutor == null) {
    animationExecutor = GlideExecutor.newAnimationExecutor();
  }
//对图片加载到内存的一个计算
  if (memorySizeCalculator == null) {
    memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
  }
//默认网络连接监控的工厂
  if (connectivityMonitorFactory == null) {
    connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
  }
//Bitmap 对象池
  if (bitmapPool == null) {
    int size = memorySizeCalculator.getBitmapPoolSize();
    if (size > 0) {
      bitmapPool = new LruBitmapPool(size);
    } else {
      bitmapPool = new BitmapPoolAdapter();
    }
  }
//数组对象池
  if (arrayPool == null) {
    arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
  }
//资源内存缓存
  if (memoryCache == null) {
    memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
  }
//磁盘缓存的工厂
  if (diskCacheFactory == null) {
    diskCacheFactory = new InternalCacheDiskCacheFactory(context);
  }
//构建执行缓存策略跟线程池的引擎
  if (engine == null) {
    engine =
        new Engine(
            memoryCache,
            diskCacheFactory,
            diskCacheExecutor,
            sourceExecutor,
            GlideExecutor.newUnlimitedSourceExecutor(),
            animationExecutor,
            isActiveResourceRetentionAllowed);
  }
  if (defaultRequestListeners == null) {
    defaultRequestListeners = Collections.emptyList();
  } else {
    defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
  }
//RequestManagerRetriever 请求管理类
  RequestManagerRetriever requestManagerRetriever =
      new RequestManagerRetriever(requestManagerFactory);
  return new Glide(
      context,
      engine,
      memoryCache,
      bitmapPool,
      arrayPool,
      requestManagerRetriever,
      connectivityMonitorFactory,
      logLevel,
      defaultRequestOptionsFactory,
      defaultTransitionOptions,
      defaultRequestListeners,
      isLoggingRequestOriginsEnabled,
      isImageDecoderEnabledForBitmaps);
}

这里就完成了Glide的构建。

然后我们回到最开始的getRetriever(activity).get(activity),看看这个函数里面都干了些什么:

java 复制代码
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
//首先判断当前是否在子线程中
  if (Util.isOnBackgroundThread()) {
//在子线程中 就通过Application级别的上下文加载
    return get(activity.getApplicationContext());
  } else {
//检查Activity是否已经销毁
    assertNotDestroyed(activity);
//拿到当前activity的fragmentmanager
    FragmentManager fm = activity.getSupportFragmentManager();
//生成一个fragment 然后绑定一个请求管理类RequestManager
    return supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
  }
}

看到这里,我们就应该意识到一个问题,如果我们在子线程中去调用Glide的话,就会使用应用级别的上下文去加载图片,这样大量使用,可能会导致内存泄漏。

然后在主线程中使用,就是Glide的精髓之一了,加载一个透明fragment来感应当前页面的生命周期的变化。

接着看看supportFragmentGet是怎么实现的:

java 复制代码
@NonNull
private RequestManager supportFragmentGet(
    @NonNull Context context,
    @NonNull FragmentManager fm,
    @Nullable Fragment parentHint,
    boolean isParentVisible) {
//在当前的 Acitivty 添加一个 Fragment 用于管理请求的生命周期
  SupportRequestManagerFragment current =
      getSupportRequestManagerFragment(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);
  }
  return requestManager;
}

这里就是添加一个fragment管理生命周期。然后返回一个RequestManager对象。

接下来再具体看看getSupportRequestManagerFragment是怎么添加的:

java 复制代码
@NonNull
private SupportRequestManagerFragment getSupportRequestManagerFragment(
    @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
//通过tag拿到fragment实例 避免重复
  SupportRequestManagerFragment current =
      (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
//没有实例的话 就去缓存找
  if (current == null) {
    current = pendingSupportRequestManagerFragments.get(fm);
//缓存也没有 就创建一个
    if (current == null) {
      current = new SupportRequestManagerFragment();
      current.setParentFragmentHint(parentHint);
      if (isParentVisible) {
        current.getGlideLifecycle().onStart();
      }
      pendingSupportRequestManagerFragments.put(fm, current);
      fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
      handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
    }
  }
  return current;
}

这里主要是拿到fragment实例。

从上面我们可以看出Glide主要是做了一些初始化的工作,缓存,线程池,复用池的构建等等。

然后绑定了一个fragment来管理生命周期

with的源码差不多就是这些,可能比较繁琐,但是不像rxjava那样绕来绕去的,主线还是比较清晰的。

五,模拟Glide生命周期管理

首先创建一个接口,监听生命周期回调:

java 复制代码
public interface LifecycleListener {
    
    void onCreate();


    void onStart();


    void onStop();


    void onDestroy();

}

然后创建一个用来管理生命周期监听的接口:

java 复制代码
public interface Lifecycle {

    void addListener(@NonNull LifecycleListener listener);

    void removeListener(@NonNull LifecycleListener listener);

}

通过上面的分析,我们知道Glide传入的上下文有应用级别的和非应用级别的。所以我们首先创建一个应用级别的Lifecycle:

java 复制代码
public class ApplicationLifecycle implements Lifecycle {

    @Override
    public void addListener(@NonNull LifecycleListener listener) {
        /**
         * APP启动的时候,执行onCreate
         */
        listener.onCreate();
    }

    @Override
    public void removeListener(@NonNull LifecycleListener listener) {
        
       //APP销毁的时候,啥也不用做了
    }
}

然后创建一个非应用级别的lifecycle:

java 复制代码
public class ActivityFragmentLifecycle implements Lifecycle {

    private final Set<LifecycleListener> lifecycleListeners =
            Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
    private boolean isStarted; 
    private boolean isDestroyed; 

    @Override
    public void addListener(@NonNull LifecycleListener listener) {
        lifecycleListeners.add(listener);

        if (isDestroyed) {
            listener.onDestroy();
        } else if (isStarted) {
            listener.onCreate();
        } else {
            listener.onStop();  
        }
    }

    @Override
    public void removeListener(@NonNull LifecycleListener listener) {
        lifecycleListeners.remove(listener);
    }

    void onStart() {
        isStarted = true;
        for (LifecycleListener lifecycleListener : lifecycleListeners) {
            lifecycleListener.onCreate();
        }
    }

    void onStop() {
        isStarted = false;
        for (LifecycleListener lifecycleListener : lifecycleListeners) {
            lifecycleListener.onStop();
        }
    }

    void onDestroy() {
        isDestroyed = true;
        for (LifecycleListener lifecycleListener : lifecycleListeners) {
            lifecycleListener.onDestroy();
        }
    }
}

创建一个具体的RequestManager 管理生命周期:

java 复制代码
public class RequestManager implements LifecycleListener {

    private Lifecycle lifecycle;

    public RequestManager(Lifecycle lifecycle, Context applicationContext) {
        this.lifecycle = lifecycle;
        this.lifecycle.addListener(this);
    }

    @Override
    public void onCreate() {
        Log.d(LOG.TAG, "yh-----onCreate");
    }

    @Override
    public void onStart() {
        Log.d(LOG.TAG, "yh-----onStart");
    }

    @Override
    public void onStop() {
        Log.d(LOG.TAG, "yh-----onStop");
    }

    @Override
    public void onDestroy() {
        Log.d(LOG.TAG, "yh-----onDestroy");
        this.lifecycle.removeListener(this);
    }
}

创建一个空白的fragment:

java 复制代码
public class RequestManagerFragment extends Fragment {

    
    private final ActivityFragmentLifecycle lifecycle;
    @Nullable
    private RequestManager requestManager;

    public RequestManagerFragment() {
        this(new ActivityFragmentLifecycle());
    }

    @VisibleForTesting
    @SuppressLint("ValidFragment")
    public RequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
        this.lifecycle = lifecycle;
    }

    public void setRequestManager(@Nullable RequestManager requestManager) {
        this.requestManager = requestManager;
    }

    @NonNull
    public ActivityFragmentLifecycle getGlideLifecycle() {
        return lifecycle;
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        this.lifecycle.addListener(requestManager);
    }

    @Nullable
    public RequestManager getRequestManager() {
        return requestManager;
    }

    @Override
    public void onDetach() {
        super.onDetach();
    }

    @Override
    public void onStart() {
        super.onStart();
        lifecycle.onStart();
    }

    @Override
    public void onStop() {
        super.onStop();
        lifecycle.onStop();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        lifecycle.onDestroy();
    }
}

简单写一个Glide管理类:

java 复制代码
public class Glide {

    private static volatile Glide glide;

    @NonNull
    public static Glide get(@NonNull Context context) {
        if (glide == null) {
            synchronized (Glide.class) {
                if (glide == null) {
                    glide = new Glide();
                }
            }
        }
        return glide;
    }

    @NonNull
    public static RequestManager with(@NonNull Context context) {
        return new RequestManager(new ActivityFragmentLifecycle(),context);
    }

    @NonNull
    public static RequestManager withApplication(@NonNull Context context) {
        return new RequestManager(new ApplicationLifecycle(),context);
    }

}

使用也很简单:

java 复制代码
public class DemoActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Glide.with(this);
        Glide.withApplication(this.getApplicationContext());
    }
}

这样当DemoActivity创建时,会创建一个ActivityFragmentLifecycle,执行它的onStart方法,从而调用RequestManager的onStart方法,onDestory也是同样的道理。这样就实现了生命周期的检测。这里只是简单写下有助于理解Glide内部是怎么做的。

关于load和into以及缓存机制 改天再写。

相关推荐
openinstall全渠道统计40 分钟前
免填邀请码工具:赋能六大核心场景,重构App增长新模型
android·ios·harmonyos
敢嗣先锋1 小时前
鸿蒙5.0实战案例:基于ImageKit对图片进行处理
移动开发·harmonyos·arkui·组件化·鸿蒙开发
敢嗣先锋1 小时前
鸿蒙5.0实战案例:基于ArkUI的验证码实现
移动开发·harmonyos·openharmony·arkui·鸿蒙开发
双鱼大猫1 小时前
一句话说透Android里面的ServiceManager的注册服务
android
双鱼大猫1 小时前
一句话说透Android里面的SystemServer进程的作用
android
双鱼大猫1 小时前
一句话说透Android里面的View的绘制流程和实现原理
android
双鱼大猫2 小时前
一句话说透Android里面的Window的内部机制
android
双鱼大猫2 小时前
一句话说透Android里面的为什么要设计Window?
android
双鱼大猫2 小时前
一句话说透Android里面的主线程创建时机,frameworks层面分析
android
苏金标3 小时前
android 快速定位当前页面
android