Glide源码分析之with方法

Glide 是一个开源的图片处理库,源代码的学习对于我们的帮助是非常大的,不过要看源码项目总得有个流程,这里我就从 Glide.with(FragmentActivity).load(URL).apply(centerCropTransform()) .into(imageViewRes); 作为阅读流程,首先就从 with(FragmentActivity) 开始开始吧。

(PS:本人阅读的源码为 Glide 4.7 版本)

首先来看下面的 with 方法的流程时序图:
这里写图片描述

接着就来依据这个时序图来阅读以下 Glide 的源码吧。

Step1 Glide.with(FragmentActivity)

    /**
     * 传入FragmentActivity对象来启动Glide并绑定FragmentActivity的生命周期,设置默认配置
     *
     * @param FragmentActivity 当前绑定的FragmentActivity
     * @return 绑定了当前activity的RequestManager, 可调用load方法加载数据
     */
    @NonNull
    public static RequestManager with(@NonNull FragmentActivity fragmentActivity) {
        return getRetriever(activity).get(activity);
    }

调用当前类的 getRetriever 方法。

Step2 Glide.getRetriever(Context)

    private static RequestManagerRetriever getRetriever(@Nullable Context context) {
        //空指针检查,context为null则直接抛出空指针异常
        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();
    }

Preconditions 这里并非 support v4 里面的那个 Preconditions 工具类, 因为后者存在着使用限制,因此 Glide 里面就直接把它需要的代码拷贝过来使用了:

/**
 * 这里是复制v4包的内部参数检查工具类,主要是检查参数是否正常,不正常就抛出异常确保外部今早发现问题
 * 个人猜测是因为v4包里面的Preconditions工具类存在某些使用限制,这里才直接复制出来
 */

public final class Preconditions {
    //代码省略
}

Step3 Glide.get(Context)

    /**
     * volatile确保内存可见性,进一步确保单例
     */
    private static volatile Glide glide;
    //..........
    /**
     * 生成或获取Glide的单例对象
     *
     * @return 单例对象
     */
    @NonNull
    public static Glide get(@NonNull Context context) {
        if (glide == null) {
            synchronized (Glide.class) {
                if (glide == null) {
                    checkAndInitializeGlide(context);
                }
            }
        }
        return glide;
    }

Step4 Glide.checkAndInitializeGlide(Context)

   /**
     * volatile确保内存可见性,进一步确保单例
     */
    private static volatile boolean isInitializing;

    private static void checkAndInitializeGlide(Context context) {
        // 在Glide初始化的过程中,可能会多次调用Glide.get(context)
        // 为避免多次初始化,这里加了一个检查判断,确保Glide对象为单例
        if (isInitializing) {
            throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"+ " use the provided Glide instance instead");
        }
        isInitializing = true;
        initializeGlide(context);
        isInitializing = false;
    }

Step4 Glide.initializeGlide()

   /**
     * Glide的初始化方法
     *
     * @param context 上下文
     */
    private static void initializeGlide(Context context) {
        initializeGlide(context, new GlideBuilder());
    }

这里创建一个 GlideBuilder 对象,它是一个用于设置 Glide 默认配置的构建者类:

/**
 * 用于设置Glide默认配置使用的构建者类
 */
public final class GlideBuilder {
    /**
     * 图片变换处理的Map集合
     * 图片变化处理就是指圆角图片之类的处理
     */
    private final Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions = new ArrayMap<>();
    /**
     * 负责启动并管理缓存资源活动的工具类
     */
    private Engine engine;
    /**
     * Lru策略的图片池,内存不足时自动清空
     */
    private BitmapPool bitmapPool;
    /**
     * Lru策略的数组池,用于读写IO,内存不足时自动清空
     */
    private ArrayPool arrayPool;
    /**
     * Lru策略的内存缓存池,内存不足时自动清空
     */
    private MemoryCache memoryCache;
    /**
     * 线程池,用于查找内存缓存,最大线程数为4,具体取决于cpu
     */
    private GlideExecutor sourceExecutor;
    /**
     * 线程池,用于查找本地磁盘缓存,最大线程数为4,具体取决于cpu
     */
    private GlideExecutor diskCacheExecutor;
    /**
     * 用于创建本地磁盘缓存对象的工厂
     * 默认本地磁盘缓存size为250M   
     */
    private DiskCache.Factory diskCacheFactory;
    /**
     * 缓存配置工具类,它通过获取手机硬件常量和手机的屏幕密度、宽度和长度来计算出最适合当前情况的缓存配置
     */
    private MemorySizeCalculator memorySizeCalculator;
    /**
     * 用于生产网络状态监听事件的工厂
     */
    private ConnectivityMonitorFactory connectivityMonitorFactory;
    /**
     * 设置Glide的log打印等级
     */
    private int logLevel = Log.INFO;
     /**
     * 设置Glide的配置选项
     */
    private RequestOptions defaultRequestOptions = new RequestOptions();
    /**
     * 用于创建RequestManager对象的工厂
     */
    @Nullable
    private RequestManagerFactory requestManagerFactory;
    /**
     * 线程池,用于加载gif图片,默认线程数为1~2,最大数取决于cpu的核数
     */
    private GlideExecutor animationExecutor;
    /**
     * 是否将保留图片资源数据不给回收,默认为false
     * 需要注意的是,设为true将会导致更大的内存消耗,增加crash的几率
     */
    private boolean isActiveResourceRetentionAllowed;
     //.....
    //构成完成 Glide对象
    public Glide build(Context context) {
        //.....
        RequestManagerRetriever requestManagerRetriever =
                new RequestManagerRetriever(requestManagerFactory);
        return new Glide(
                context,
                engine,
                memoryCache,
                bitmapPool,
                arrayPool,
                requestManagerRetriever,
                connectivityMonitorFactory,
                logLevel,
                defaultRequestOptions.lock(),
                defaultTransitionOptions);
    }
    }

可以看到,Glide 的初始化其实就是 GlideBuilder 来完成的。下面就是 Glide 完成实例的过程了:

 private static void initializeGlide(Context context, GlideBuilder builder) {
        Context applicationContext = context.getApplicationContext();
        GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
        List<GlideModule> manifestModules = Collections.emptyList();
        //如果没有注解生成的Module就去读取清单文件,检查是否有module
        if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
            manifestModules = new ManifestParser(applicationContext).parse();
        }
        //如果有注解生成的Module就对比一下清单文件获取的module
        //删除相同的module
        if (annotationGeneratedModule != null
                && !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
            Set<Class<?>> excludedModuleClasses =
                    annotationGeneratedModule.getExcludedModuleClasses();
            Iterator<GlideModule> iterator = manifestModules.iterator();
            while (iterator.hasNext()) {
                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();
            }
        }
        //打印出从清单文件中获取到的有效module
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            for (GlideModule glideModule : manifestModules) {
                Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
            }
        }
        //初始化请求工厂
        RequestManagerRetriever.RequestManagerFactory factory =
                annotationGeneratedModule != null
                        ? annotationGeneratedModule.getRequestManagerFactory() : null;
        builder.setRequestManagerFactory(factory);
        for (GlideModule module : manifestModules) {
            //回调给外层调用者提供GlideBuilder来修改默认配置
            module.applyOptions(applicationContext, builder);
        }
        if (annotationGeneratedModule != null) {
            //如果有注解生成的Module
            //回调给外层调用者提供GlideBuilder来修改默认配置
            annotationGeneratedModule.applyOptions(applicationContext, builder);
        }
        Glide glide = builder.build(applicationContext);
        for (GlideModule module : manifestModules) {
            //回调给外层调用者提供registry工厂管理类来修改默认配置
            module.registerComponents(applicationContext, glide, glide.registry);
        }
        if (annotationGeneratedModule != null) {
            //如果有注解生成的Module
            //回调给外层调用者提供registry工厂管理类来修改默认配置
            annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
        }
        //监听App的内存变化,内存紧张时把BitmapPool、MemoryCache和ArrayPool都清空
        applicationContext.registerComponentCallbacks(glide);
        //完成单例的实例化
        Glide.glide = glide;
    }

关于 Glide 设置外层的 Module 来修改一些默认配置,这类在网上已经有很多资源了,这里就不多说什么了。

如果想搞明白 Glide 如何通过清单文件加载 Molude 可以看这篇 blog

Step5 Glide.getRequestManagerRetriever()

    /**
     * @return 返回一个RequestManager的管理工具类
     */
    public RequestManagerRetriever getRequestManagerRetriever() {
        return requestManagerRetriever;
    }

RequestManagerRetrieverHandler.CallBack 实现类,同时也是生命周期的一个管理类:

/**
 * 一个生成或获取RequestManager的管理工具类
 * 它可以从绑定的Activity或Fragment中接收存在的RequestManager对象
 * 同时在RequestManager上面获取存在的感知外层生命周期的Fragment
 * 如果不存在该对象,就生成一个新的RequestManager
 * 在生成新的RequestManager同时也生成感知外层生命周期的Fragment
 */
public class RequestManagerRetriever implements Handler.Callback {
   //代码暂时省略
}

Step6 RequestManagerRetriever.get(FragmentActivity)

public RequestManager get(@NonNull FragmentActivity activity) {
        //检查是否在子线程执行
        if (Util.isOnBackgroundThread()) {
            //暂时忽略子线程启动的流程
            return get(activity.getApplicationContext());
        }
        //检查activity是否销毁了
        assertNotDestroyed(activity);
        //拿到v4包的Fragment管理器
        FragmentManager fm = activity.getSupportFragmentManager();
        return supportFragmentGet(
                activity, fm, null, isActivityVisible(activity));
    }

这里暂时先忽略子线程启动的流程,以后再来给大家介绍。

这里可以看到 Glide 会检查当前传入的 activity 的状态:

   /**
     * Android 4.2以上执行,判断当前Activity是否销毁了(activity.isDestroyed()是4.2以上才有的api)
     *
     * @param activity 当前activity
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    private static void assertNotDestroyed(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed()) {
            throw new IllegalArgumentException("You cannot start a load for a destroyed activity");
        }
    }

可以看到这个判断方法只在 Android 4.2 上面执行,一旦发现传递进来的 activity 已经销毁了,那么就会抛出异常了,在使用 Glide 时必须注意到这一点。

Step7 RequestManagerRetriever.supportFragmentGet()

   /**
     * 获取一个感知外层生命周期的Fragment和网络请求管理类RequestManager
     * 并让Fragment持有RequestManager
     *
     * @param context         当前传入的上下文
     * @param fm              Fragment管理器
     * @param parentHint      可以传null,外层传入的Fragment
     * @param isParentVisible 是否显示
     * @return RequestManager {@link exercise.fritz.com.glide.RequestManager}
     */
    @NonNull
    private RequestManager supportFragmentGet(
            @NonNull Context context,
            @NonNull FragmentManager fm,
            @Nullable Fragment parentHint,
            boolean isParentVisible) {
        //获取到当前用于感知外层生命周期的Fragment
        SupportRequestManagerFragment current =
                getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
        //获取Fragment上面的请求工具类
        RequestManager requestManager = current.getRequestManager();
        //如果是空,则生成一个新的
        if (requestManager == null) {
            Glide glide = Glide.get(context);
            requestManager = mRwFactory.build(glide, 
                                     current.getGlideLifecycle(),
                                    current.getRequestManagerTreeNode(), context);
            current.setRequestManager(requestManager);
        }
        return requestManager;
    }

关于 Glide 感知外层生命周期的原理具体可以看我的这篇 blog 。上面的代码我都写上了中文注释,不过 getSupportRequestManagerFragment 与其相关的方法参数,还是需要看一下的:

    /**
     * handler发消息的标记,通知清空pendingSupportRequestManagerFragments Map里面的数据
     */
    private static final int ID_REMOVE_SUPPORT_FRAGMENT_MANAGER = 2;   

    /**
     * 存储外层感知生命周期的v4包的Fragment集合
     */
    final Map<FragmentManager, SupportRequestManagerFragment> 
    pendingSupportRequestManagerFragments = new HashMap<>(); 

    /**
     * 获取当前Activity上面的感知生命周期的SupportRequestManagerFragment
     * 如果没有,就生成一个新的
     *
     * @param fm              Fragment管理器
     * @param parentHint      可以是null,外层传入的Fragment
     * @param isParentVisible 是否显示
     * @return 感知外层生命周期的Fragment
     */
    public SupportRequestManagerFragment getSupportRequestManagerFragment(
            @NonNull FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible)    {
        //寻找当前显示的Glide用来感知外层生命周期的Fragment
        SupportRequestManagerFragment current =
                (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
        //如果为null,生成一个新的感知外层生命周期的Fragment
        if (current == null) {
            //使用map的key确保一个FragmentManager同一时间只生成一个感知生命周期的Fragment
            current = pendingSupportRequestManagerFragments.get(fm);
            if (current == null) {
                current = new SupportRequestManagerFragment();
                current.setParentFragmentHint(parentHint);
                //如果外层是显示状态
                if (isParentVisible) {
                    //启动生命周期监听的回调
                    current.getGlideLifecycle().onStart();
                }
                //存储当前的感知外层生命周期的fragment
                pendingSupportRequestManagerFragments.put(fm, current);
                //提交运行fragment
                fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
                //发送消息,清空刚存进去的Fragment
                mHandler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
            }
        }
        return current;
    }

这里生成或获取一个可以感知外层生命周期的 Fragment ,值得一提就是这里使用了一个 map 来确保一个 FragmentManager 同一时间只生成一个感知生命周期的 Fragment ,一旦 Fragment 顺利生成后再又把它在 map 里面清空:

    @Override
    public boolean handleMessage(Message msg) {
        boolean handled = true;
        Object removed = null;
        Object key = null;
        switch (msg.what) {
            case ID_REMOVE_SUPPORT_FRAGMENT_MANAGER:
                FragmentManager supportFm = (FragmentManager) msg.obj;
                key = supportFm;
                removed = pendingSupportRequestManagerFragments.remove(supportFm);
                break;
            default:
                handled = false;
                break;
        }
        if (handled && removed == null && Log.isLoggable(TAG, Log.WARN)) {
            Log.w(TAG, "Failed to remove expected request manager fragment, manager: " + key);
        }
        return handled;
    }

### Step8 RequestManagerRetriever.RequestManagerFactory.build()

在上面的 supportFragmentGet 方法里面,我们看到了一个 mRwFactory 对象,它生成了一个全新的 RequestManager ,它其实就是 RequestManagerRetriever 的一个内部类:

    /**
     * 用于创建RequestManager的工厂接口
     */
    public interface RequestManagerFactory {
        @NonNull
        RequestManager build(
                @NonNull Glide glide,
                @NonNull Lifecycle lifecycle,
                @NonNull RequestManagerTreeNode requestManagerTreeNode,
                @NonNull Context context);
    } 

而且在 RequestManagerRetriever 里面已经有一个简单的静态单例的默认实现了:

 /**
  * 用于创建RequestManager的工厂接口实现对象
  */
private static final RequestManagerFactory DEFAULT_FACTORY = new RequestManagerFactory() {
        @NonNull
        @Override
        public RequestManager build(@NonNull Glide glide, @NonNull Lifecycle lifecycle,
                                    @NonNull RequestManagerTreeNode requestManagerTreeNode,
                                    @NonNull Context context) {
            return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
        }
    };

mRwFactory 就是在构造方法里面给赋值的:

public RequestManagerRetriever(@Nullable RequestManagerFactory factory) {
        mHandler = new Handler(Looper.getMainLooper(), this);
        mRwFactory = factory != null ? factory : DEFAULT_FACTORY;
}

到此,Glidewith(FragmentActivity) 的流程就全部解析完成了,不过还是从中学到了一些东西,其中包括:

  1. 通过清单文件反射加载外层文件的方法
  2. private static 的代码规范
  3. 通过 Fragment 来感知外层生命周期的方法

我这里介绍的流程就只是 Glide 众多使用流程里面的比较简单的一个,不过看懂一个主流程后,再看其他的流程,心里就有底了。

下次见面给大家介绍一下 load(URL) 里面流程了,这些都是 RequestManager 里面的一些处理了,还请期待。

猜你喜欢

转载自blog.csdn.net/f409031mn/article/details/80984650