初始化:Glide.java

Posted bdmh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初始化:Glide.java相关的知识,希望对你有一定的参考价值。

这篇文章,我们从Glide.with来展开了解一下Glide的源码。

Glide.with有多个重载,with方法的参数有可能是Context、Activity、Fragment等。

请记住一点,Glide的context需要是Application级别的Context,不要在生命周期事件中开始和停止。

下面的方法可以在fragment 或 activity 生命周期之外使用 (比如 services,notification thumbnails).

  public static RequestManager with(@NonNull Context context) 
    return getRetriever(context).get(context);
  

下面这个和给定的Activity的生命周期绑定并使用它默认的配置

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

下面这个针对 androidx.fragment.app.FragmentActivity 类型的

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

下面这个针对 androidx.fragment.app.Fragment 类型的 

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

 下面这个针对android.app.Fragment类型

  public static RequestManager with(@NonNull android.app.Fragment fragment) 
    return getRetriever(fragment.getActivity()).get(fragment);
  

下面这个是在View中使用的 

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

我们在所有的with方法中,都看到了getRetriever这个函数。

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();

该方法,返回RequestManagerRetriever对象,RequestManagerRetriever是一个提供了一些静态方法,用来创建com.bumptech.glide.RequestManager实例,并可以在activity和fragment中检索对应的com.bumptech.glide.RequestManager对象。

在Glide内部有RequestManagerRetriever变量声明,并且在Glide初始化时,赋值。

private final RequestManagerRetriever requestManagerRetriever;

到现在,我们依然没有看到Glide是如何创建的,不创建,那怎么使用呢?马上来了,看这句话

Glide.get(context).getRequestManagerRetriever()
private static volatile Glide glide;

//双锁机制创建单例
public static Glide get(@NonNull Context context) 
    if (glide == null) 
        //这里会动态生成代码,我们可以自定义Module来配置Glide
        GeneratedAppGlideModule annotationGeneratedModule =
                getAnnotationGeneratedGlideModules(context.getApplicationContext());
        synchronized (Glide.class) 
            if (glide == null) 
                //c创建
                checkAndInitializeGlide(context, annotationGeneratedModule);
            
        
    

    return glide;

在Glide内部,定义了一个私有的静态变量glide,看上面的代码就很清楚的看到,Glide内部使用的是单例模式。在get方法中,使用了检测双锁的机制,来创建单例。

GeneratedAppGlideModule 我们后面文章讲解。继续看代码。

private static void checkAndInitializeGlide(
        @NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) 
    // 在initGlide()线程中, Glide.get(context)会被多次调用
    // 如果没有下面的判断, 会引起递归.
    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;

最终会调用下面的方法初始化Glide。我们暂时先略过和Module相关的代码。

private static void initializeGlide(
        @NonNull Context context,
        @NonNull GlideBuilder builder,
        @Nullable GeneratedAppGlideModule annotationGeneratedModule)
    ......
//获取Application级别的Context
    Context applicationContext = context.getApplicationContext();
//Build模式创建Glide实例
    Glide glide = builder.build(applicationContext);
    ......
//赋值给单例对象
    Glide.glide = glide;

builder.build方法中会调用Glide的初始化。《GlideBuilder》

Glide build(@NonNull Context context) 
......
    return new Glide(
//上下文-ApplicationContext
            context,
//用来加载和管理活动和缓存中资源的
            engine,
//MemoryCache接口,管理缓存中资源的
            memoryCache,
//bitmap池子,用来复用图像的
            bitmapPool,
//数组池子,管理各种数组对象
            arrayPool,
//前面提到的 RequestManagerRetriever 实例
            requestManagerRetriever,
//工厂类,负责产生ConnectivityMonitor对象
//ConnectivityMonitor是用来监控网络事件的
            connectivityMonitorFactory,
//日志级别,默认Log.INFO
            logLevel,
//提供各种options配置
            defaultRequestOptionsFactory,
//资源加载完后的过度效果,比如bitmap的动画效果
//Map结构
            defaultTransitionOptions,
//加载图像监听
            defaultRequestListeners,
            experiments);

Glide的构造方法中,代码非常多,大概就是下面几大块。

把上面的参数,赋值给内部变量

Glide(......)
    this.engine = engine;
    this.bitmapPool = bitmapPool;
    this.arrayPool = arrayPool;
    this.memoryCache = memoryCache;
    this.requestManagerRetriever = requestManagerRetriever;
    this.connectivityMonitorFactory = connectivityMonitorFactory;
    this.defaultRequestOptionsFactory = defaultRequestOptionsFactory;    

获取资源对象

final Resources resources = context.getResources();

注册组件。Glide有一个Registry类,专门负责管理组件的,比如Module、编码解码、过度效果等等。我们来看一个我们接触最多的组件。

Glide(......)
    registry.append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory());

上面这个就是注册一个用来下载图像的网络组件HttpGlideUrlLoader。它内部使用的是HttpURLConnection组件进行网络请求的。这个是可以替换的,后面再讲。

最后,会初始化一个全局的GlideContext,给Glide中所有注册的内部以及对外组件访问资源用的。

Glide(......)
    glideContext =
            new GlideContext(
                    context,
                    arrayPool,
                    registry,
                    imageViewTargetFactory,
                    defaultRequestOptionsFactory,
                    defaultTransitionOptions,
                    defaultRequestListeners,
                    engine,
                    experiments,
                    logLevel);
);

到这,一个Glide单例对象,就被创建好了,我们就可以在项目中使用了。

以上是关于初始化:Glide.java的主要内容,如果未能解决你的问题,请参考以下文章

初始化:Glide.java

Glide:DecodeHelper

Glide:DecodeHelper

Glide:DecodeHelper

Glide:GlideBuilder

Glide:GlideBuilder