安卓开源库学习之Glide的使用及源码阅读

背景

我在安卓开发学习之Picasso源码简析中介绍了图片加载库Picasso的使用,并分析了其源码。做为和Picasso并驾齐驱的开源图片加载库Glide,功能更强大,体积也更大,我觉得也应该看一下


使用步骤

1、添加依赖

    compile 'com.github.bumptech.glide:glide:3.7.0'
    // Glide依赖
    compile 'com.android.support:support-v4:27.1.1'

添加v4的依赖是因为Glide内部利用了Fragment


2、加载图片

Glide加载图片步骤和Picasso是一样的

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mImage = findViewById(R.id.image);

        String url = "https://images7.alphacoders.com/789/thumb-1920-789672.jpg";
        Glide.with(this).load(url).into(mImage);
    }


效果


源码阅读

Glide#with(activity)

方法源码如下

    public static RequestManager with(Activity activity) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get(); // 获取RequestManagerRetriever的单例
        return retriever.get(activity);
    }

调用了RequestManagerRetriever的get(activity)方法,源码如下

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public RequestManager get(Activity activity) {
        if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
            return get(activity.getApplicationContext());
        } else {
            assertNotDestroyed(activity);
            android.app.FragmentManager fm = activity.getFragmentManager();
            return fragmentGet(activity, fm);
        }
    }

如果是在后台线程(也就是非主线程)或sdk<11(这个一般是false,sdk11对应Android3.0,很老的版本了),调用了get(context)方法,此方法代码如下

    public RequestManager get(Context context) {
        if (context == null) { // 传进来的是null,直接抛异常
            throw new IllegalArgumentException("You cannot start a load on a null Context");
        } else if (Util.isOnMainThread() && !(context instanceof Application)) { // 如果是在主线程上,并且传进来的不是Application对象
            if (context instanceof FragmentActivity) { // 如果传进来的是FragmentActivity
                return get((FragmentActivity) context);
            } else if (context instanceof Activity) { // 如果传进来的是Activity
                return get((Activity) context);
            } else if (context instanceof ContextWrapper) { // 如果传进来的是Activity的父类ContextWrapper
                return get(((ContextWrapper) context).getBaseContext());
            }
        }

        return getApplicationManager(context); // 如果传进来的不是FragmentActivity、Activity、ContextWrapper,就获取ApplicationManager
    }

通过看前面的get(activity),发现这里是由非主线程的分支走过来的,并且传进来的是ApplicationContext,这是一个Application对象,所以最后调用的是getApplicationManager(context)方法,代码如下

    private RequestManager getApplicationManager(Context context) {
        // Either an application context or we're on a background thread.
        if (applicationManager == null) {
            synchronized (this) {
                if (applicationManager == null) {
                    // Normally pause/resume is taken care of by the fragment we add to the fragment or activity.
                    // However, in this case since the manager attached to the application will not receive lifecycle
                    // events, we must force the manager to start resumed using ApplicationLifecycle.
                    applicationManager = new RequestManager(context.getApplicationContext(),
                            new ApplicationLifecycle(), new EmptyRequestManagerTreeNode());
                }
            }
        }

        return applicationManager;
    }

就是返回一个RequestManager单例,构造方法传入的参数分别是应用上下文、应用生命周期、空的请求树,暂时不用管


返回RequestManagerRetriever的get(activity)方法,如果是在主线程,就通过activity的FragmentManager,调用fragmentGet()方法,代码如下

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
        RequestManagerFragment current = getRequestManagerFragment(fm);
        RequestManager requestManager = current.getRequestManager();
        if (requestManager == null) {
            requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
            current.setRequestManager(requestManager);
        }
        return requestManager;
    }

调用了getRequestManagerFragment()方法,代码如下

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm) {
        RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG); // 第一次使用的话,这里肯定是null
        if (current == null) {
            current = pendingRequestManagerFragments.get(fm); // pendingRequestManagerFragments是一个哈希映射,但我们第一次进去,肯定也是返回null
            if (current == null) {
                current = new RequestManagerFragment(); // 构造一个RequestManagerFragment
                pendingRequestManagerFragments.put(fm, current); // 存入哈希映射
                fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss(); // 开始进行fragment转换,添加标签,不进行状态检查
                handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
            }
        }
        return current;
    }

fragment转换完成后,给自己send一个ID_REMOVE_FRAGMENT_MANAGER消息,把刚刚存入的RequestManagerFragment从哈希映射中去掉

    @Override
    public boolean handleMessage(Message message) {
        boolean handled = true;
        Object removed = null;
        Object key = null;
        switch (message.what) {
            case ID_REMOVE_FRAGMENT_MANAGER:
                android.app.FragmentManager fm = (android.app.FragmentManager) message.obj;
                key = fm;
                removed = pendingRequestManagerFragments.remove(fm);
                break;
            ...
        }
        ...
        return handled;
    }

返回getRequestManagerFragment()方法,一切正常的话,就会返回新建的RequestManagerFragment对象到fragmentGet()方法中,而后调用RequestManagerFragment的getRequestManager()方法,获取它的requestManager对象,但是RequestManagerFragment的构造方法里,只会初始化自己的ActivityFragmentLifeCycle,不会实例化requestManager,所以RequestManagerFragment的getRequestManager()方法返回null,然后就是构造一个requestManager对象,set给RequestManagerFragment,最后返回requestManager对象

这样,一路返回,Glide.with(activity)也执行完了,返回的是一个RequestManager,那load()方法执行的就是RequestManager.load()方法


RequestManager#load(string)

代码如下

    public DrawableTypeRequest<String> load(String string) {
        return (DrawableTypeRequest<String>) fromString().load(string);
    }

调用了fromString()方法,代码如下

    public DrawableTypeRequest<String> fromString() {
        return loadGeneric(String.class); // 似乎用了反射
    }

调用了loadGeneric()方法,传入的是class

    private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) {
        ModelLoader<T, InputStream> streamModelLoader = Glide.buildStreamModelLoader(modelClass, context);
        ModelLoader<T, ParcelFileDescriptor> fileDescriptorModelLoader =
                Glide.buildFileDescriptorModelLoader(modelClass, context);
        if (modelClass != null && streamModelLoader == null && fileDescriptorModelLoader == null) {
            throw new IllegalArgumentException("Unknown type " + modelClass + ". You must provide a Model of a type for"
                    + " which there is a registered ModelLoader, if you are using a custom model, you must first call"
                    + " Glide#register with a ModelLoaderFactory for your custom model class");
        }

        return optionsApplier.apply(
                new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context,
                        glide, requestTracker, lifecycle, optionsApplier));
    }
进入Glide.buildStreamModelLoader()方法
    public static <T> ModelLoader<T, InputStream> buildStreamModelLoader(Class<T> modelClass, Context context) {
        return buildModelLoader(modelClass, InputStream.class, context);
    }

进入buildModelLoader方法

    public static <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass,
            Context context) {
         if (modelClass == null) {
            .. 
        }
        return Glide.get(context).getLoaderFactory().buildModelLoader(modelClass, resourceClass);
    }

传入的class当然不是空,而后进入Glide.get(context)方法

    public static Glide get(Context context) {
        if (glide == null) {
            synchronized (Glide.class) {
                if (glide == null) {
                    Context applicationContext = context.getApplicationContext();
                    List<GlideModule> modules = new ManifestParser(applicationContext).parse();

                    GlideBuilder builder = new GlideBuilder(applicationContext);
                    for (GlideModule module : modules) {
                        module.applyOptions(applicationContext, builder);
                    }
                    glide = builder.createGlide();
                    for (GlideModule module : modules) {
                        module.registerComponents(applicationContext, glide);
                    }
                }
            }
        }

        return glide;
    }

其实就是获取Glide单例,debug到此处时,发现之前没有察觉到Glide单例的创建,但这里单例却不是null,原因何在。其实早在我们构造RequestManager的时候,就调用了这个Glide.get()方法,而且,一路跟过来的context参数,也是RequestManager的context对象,同样是在RequestManager的构造方法中传入的,这个构造方法代码如下

    public RequestManager(Context context, Lifecycle lifecycle, RequestManagerTreeNode treeNode) { // 这是我们实际调用的
        this(context, lifecycle, treeNode, new RequestTracker(), new ConnectivityMonitorFactory());
    }

    RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,
            RequestTracker requestTracker, ConnectivityMonitorFactory factory) {
        this.context = context.getApplicationContext(); // 传入的context是Activity,但为了避免内存泄漏,这里赋值的是应用的上下文
        this.lifecycle = lifecycle; // RequestManagerFragment里的ActivtiyFragmentLifeCycle对象
        this.treeNode = treeNode; // null
        this.requestTracker = requestTracker; // new出来的RequestTracker对象
        this.glide = Glide.get(context); // 调用Gilde.get()方法获取单例
        this.optionsApplier = new OptionsApplier();

        ConnectivityMonitor connectivityMonitor = factory.build(context,
                new RequestManagerConnectivityListener(requestTracker)); // 构造ConnectivityMonitor

        // 给lifeCycle添加监听,监听为RequestManager本身
        if (Util.isOnBackgroundThread()) {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    lifecycle.addListener(RequestManager.this); 
                }
            });
        } else {
            lifecycle.addListener(this);
        }
        lifecycle.addListener(connectivityMonitor); // 给lifeCycle添加监听,监听是ConnectivityMonitor
    }

大体看过后,回到Glide.get(context)方法

    public static Glide get(Context context) {
        if (glide == null) {
            synchronized (Glide.class) {
                if (glide == null) {
                    Context applicationContext = context.getApplicationContext(); // 本身就是全局上下文
                    List<GlideModule> modules = new ManifestParser(applicationContext).parse(); // 获取当前项目中的所有GlideModule,存在meta-data里,默认没有

                    GlideBuilder builder = new GlideBuilder(applicationContext); // 构造GlideBuilder,传入全局上下文
                    for (GlideModule module : modules) { // 这个循环可以忽略
                        module.applyOptions(applicationContext, builder);
                    }
                    glide = builder.createGlide();
                    for (GlideModule module : modules) { // 这个循环可以忽略
                        module.registerComponents(applicationContext, glide);
                    }
                }
            }
        }

        return glide;
    }

主要是调用了GildeBuilder.createGlide()方法,代码如下

    Glide createGlide() {
        if (sourceService == null) {
            final int cores = Math.max(1, Runtime.getRuntime().availableProcessors());
            sourceService = new FifoPriorityThreadPoolExecutor(cores); // 获取服务端或网络数据用的线程池,容量是手机cpu数量,先进先出,并行的
        }
        if (diskCacheService == null) {
            diskCacheService = new FifoPriorityThreadPoolExecutor(1); // 存入缓存用的线程池,容量是1,先进先出,也就是串行的
        }

        MemorySizeCalculator calculator = new MemorySizeCalculator(context); // 内存大小计算器
        if (bitmapPool == null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // Android3.0以上的bitmapPool遵循LRU(清除最近最久未使用的对象)原则
                int size = calculator.getBitmapPoolSize();
                bitmapPool = new LruBitmapPool(size);
            } else {
                bitmapPool = new BitmapPoolAdapter();
            }
        }

        if (memoryCache == null) {
            memoryCache = new LruResourceCache(calculator.getMemoryCacheSize()); // 内存缓存也是用的LRU算法
        }

        if (diskCacheFactory == null) {
            diskCacheFactory = new InternalCacheDiskCacheFactory(context); // 存盘缓存
        }

        if (engine == null) {
            engine = new Engine(memoryCache, diskCacheFactory, diskCacheService, sourceService); // 加载器,是加载网络图片或存储空间图片的主力
        }

        if (decodeFormat == null) {
            decodeFormat = DecodeFormat.DEFAULT; // 默认解码器
        }

        return new Glide(engine, memoryCache, bitmapPool, context, decodeFormat); 
    }

构造完组件后,就new一个Glide对象返回。

当然,我们从Glide.buildModeLoader()进入的,单例不是null,直接就从Glide.get()里返回了。然后调用glide.getLoaderFactory()方法,获取loaderFactory对象,这个对象是在Glide的构造方法中被初始化的,是一个GenericFactory对象,最后调用genericLoaderFactory的buildModelLoader()方法,传入参数分别是String的class和InputStream.class,方法代码如下

    public synchronized <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass) {
        ModelLoader<T, Y> result = getCachedLoader(modelClass, resourceClass); // 从缓存中读取,第一次进入,返回null
        if (result != null) {
            // 如果缓存中有我们的ModelLoader,就看情况返回,但第一次加载肯定是没有缓存的
            if (NULL_MODEL_LOADER.equals(result)) {
                return null;
            } else {
                return result;
            }
        }

        final ModelLoaderFactory<T, Y> factory = getFactory(modelClass, resourceClass);
        if (factory != null) {
            result = factory.build(context, this);
            cacheModelLoader(modelClass, resourceClass, result);
        } else {
            // We can't generate a model loader for the given arguments with the currently registered set of factories.
            cacheNullLoader(modelClass, resourceClass);
        }
        return result;
    }

由于我们第一次启动,所以缓存里没有东西,直接到getFactory()方法里,代码如下

    private <T, Y> ModelLoaderFactory<T, Y> getFactory(Class<T> modelClass, Class<Y> resourceClass) {
        Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/> resourceToFactories = modelClassToResourceFactories.get(modelClass);
        ModelLoaderFactory/*T, Y*/ result = null;
        if (resourceToFactories != null) {
            result = resourceToFactories.get(resourceClass);
        }

        if (result == null) {
            .. // 其他情况
        }

        return result;
    }

从modelClassToResourceFactories这个哈希映射里通过modelClass获取叫做resourceToFactories的哈希映射,这个modelClassToResourceFactories早在Glide的构造方法中就已经添加了内容,相关代码如下

    Glide(Engine engine, MemoryCache memoryCache, BitmapPool bitmapPool, Context context, DecodeFormat decodeFormat) {
        ..
        loaderFactory = new GenericLoaderFactory(context);
        ..

        register(File.class, ParcelFileDescriptor.class, new FileDescriptorFileLoader.Factory());
        register(File.class, InputStream.class, new StreamFileLoader.Factory());
        register(int.class, ParcelFileDescriptor.class, new FileDescriptorResourceLoader.Factory());
        register(int.class, InputStream.class, new StreamResourceLoader.Factory());
        register(Integer.class, ParcelFileDescriptor.class, new FileDescriptorResourceLoader.Factory());
        register(Integer.class, InputStream.class, new StreamResourceLoader.Factory());
        register(String.class, ParcelFileDescriptor.class, new FileDescriptorStringLoader.Factory());
        register(String.class, InputStream.class, new StreamStringLoader.Factory());
        register(Uri.class, ParcelFileDescriptor.class, new FileDescriptorUriLoader.Factory());
        register(Uri.class, InputStream.class, new StreamUriLoader.Factory());
        register(URL.class, InputStream.class, new StreamUrlLoader.Factory());
        register(GlideUrl.class, InputStream.class, new HttpUrlGlideUrlLoader.Factory());
        register(byte[].class, InputStream.class, new StreamByteArrayLoader.Factory());
        ..
    }

Glide.register()方法代码如下

    public <T, Y> void register(Class<T> modelClass, Class<Y> resourceClass, ModelLoaderFactory<T, Y> factory) {
        ModelLoaderFactory<T, Y> removed = loaderFactory.register(modelClass, resourceClass, factory); // 注册,并获取之前注册的ModelLoaderFactory
        if (removed != null) {
            removed.teardown(); // 销毁之前的ModelLoaderFactory
        }
    }

我们知道,这里的loaderFactory就是GenericLoaderFactory,它的register()方法代码如下

    public synchronized <T, Y> ModelLoaderFactory<T, Y> register(Class<T> modelClass, Class<Y> resourceClass,
            ModelLoaderFactory<T, Y> factory) {
        cachedModelLoaders.clear(); // 每次注册,都清空缓存

        Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/> resourceToFactories = modelClassToResourceFactories.get(modelClass); // 先获取以前的modelClass对应的内容,也是一个哈希映射
        if (resourceToFactories == null) { // 以前内容是空的话
            resourceToFactories = new HashMap<Class/*Y*/, ModelLoaderFactory/*T, Y*/>(); // 构造一个新的hashMap
            modelClassToResourceFactories.put(modelClass, resourceToFactories); // 把新的哈希映射做为值,modelClass做为键,存入modelClassToResourceFactories
        }

        ModelLoaderFactory/*T, Y*/ previous = resourceToFactories.put(resourceClass, factory); // 把参数保存到做为内容的哈希映射中,同时获取老的ModelLoaderFactory

        if (previous != null) { // 如果老的ModelLoaderFactory不是null,置空之
            // This factory may be being used by another model. We don't want to say it has been removed unless we
            // know it has been removed for all models.
            for (Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/> factories : modelClassToResourceFactories.values()) {
                if (factories.containsValue(previous)) {
                    previous = null;
                    break;
                }
            }
        }

        return previous;
    }

所以RequestManager.load()里面可以传入的有String、URI、URL、File、Integer、byte数组这些东西,而这些表示图片或图片位置的参数对应的结果也各有各的不同,比如String就对应了InputStream和FileDescriptor两种


返回GenericLoaderFactory.getFactory(),我们根据String.class成功从modelClassToResourceFactories映射中获取了resourceToFactories映射,而且不是null,然后返回这个映射到了GenericLoaderFactory.getFactory()方法中,然后根据resourceClass(也就是InputStream.class)获取对应的ModelLoaderFactory,结果是StreamStringLoader.Factory对象

    private <T, Y> ModelLoaderFactory<T, Y> getFactory(Class<T> modelClass, Class<Y> resourceClass) {
        Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/> resourceToFactories = modelClassToResourceFactories.get(modelClass);
        ModelLoaderFactory/*T, Y*/ result = null;
        if (resourceToFactories != null) {
            result = resourceToFactories.get(resourceClass); // 此处是StreamStringLoader.Factory对象,ModelLoaderFactory是一个接口,StreamStringLoader.Factory是它的实现类之一
        }

        if (result == null) {
            .. 
        }

        return result;
    }

而后返回这个StreamStringLoader到GenericLoaderFactory.buildModelLoader()方法中

    public synchronized <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass) {
        ModelLoader<T, Y> result = getCachedLoader(modelClass, resourceClass);
        if (result != null) {
            // 缓存
            if (NULL_MODEL_LOADER.equals(result)) {
                return null;
            } else {
                return result;
            }
        }

        final ModelLoaderFactory<T, Y> factory = getFactory(modelClass, resourceClass); // 已经获取到了StreamStringLoader.Factory
        if (factory != null) {
            result = factory.build(context, this);
            cacheModelLoader(modelClass, resourceClass, result);
        } else {
            // We can't generate a model loader for the given arguments with the currently registered set of factories.
            cacheNullLoader(modelClass, resourceClass);
        }
        return result;
    }

而后调用StreamStringLoader.Factory.build()方法,代码如下

public class StreamStringLoader extends StringLoader<InputStream> implements StreamModelLoader<String> {

    /**
     * The default factory for {@link com.bumptech.glide.load.model.stream.StreamStringLoader}s.
     */
    public static class Factory implements ModelLoaderFactory<String, InputStream> {
        @Override
        public ModelLoader<String, InputStream> build(Context context, GenericLoaderFactory factories) {
            return new StreamStringLoader(factories.buildModelLoader(Uri.class, InputStream.class)); // 把String.class换成Uri.class
        }

        @Override
        public void teardown() {
            // Do nothing.
        }
    }

    public StreamStringLoader(Context context) {
        this(Glide.buildStreamModelLoader(Uri.class, context));
    }

    public StreamStringLoader(ModelLoader<Uri, InputStream> uriLoader) {
        super(uriLoader);
    }
}

执行过程就是把String.class换成Uri.class,再执行一遍GenericLoaderFactory.buildModelLoader()方法,经过GenericLoaderFactory.getFactory()方法,获取到的是StreamUriLoader.Factory,再调用StreamUriLoader.Factory.build()方法,此时把Uri.class换成GlideUrl.class,再执行一遍GenericLoaderFactory.buildModelLoader()方法,经过GenericLoaderFactory.getFactory()方法,获取到的是HttpUrlGlideUrlLoader.Factory,最后调用它的build()方法,获取到一个HttpUrlGlideUrlLoader,这部分的代码如下

public class HttpUrlGlideUrlLoader implements ModelLoader<GlideUrl, InputStream> {

    private final ModelCache<GlideUrl, GlideUrl> modelCache;

    /**
     * The default factory for {@link com.bumptech.glide.load.model.stream.HttpUrlGlideUrlLoader}s.
     */
    public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
        private final ModelCache<GlideUrl, GlideUrl> modelCache = new ModelCache<GlideUrl, GlideUrl>(500);

        @Override
        public ModelLoader<GlideUrl, InputStream> build(Context context, GenericLoaderFactory factories) {
            return new HttpUrlGlideUrlLoader(modelCache); // 返回的是一个HttpUrlGlideUrlLoader,附带容量是500的缓存
        }

        @Override
        public void teardown() {
            // Do nothing.
        }
    }

    ...
}

然后一路返回并缓存,GenericLoaderFactory.buildModeLoader()方法也执行完了,再一路返回,回到RequestManager.loadGeneric()方法,这是我们执行完了第一行代码,获得了一个StreamStringLoader对象

    private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) {
        ModelLoader<T, InputStream> streamModelLoader = Glide.buildStreamModelLoader(modelClass, context); // 获取到的是一个StringStreamLoader对象
        ModelLoader<T, ParcelFileDescriptor> fileDescriptorModelLoader =
                Glide.buildFileDescriptorModelLoader(modelClass, context);
        if (modelClass != null && streamModelLoader == null && fileDescriptorModelLoader == null) {
            // 异常
        }

        return optionsApplier.apply(
                new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context,
                        glide, requestTracker, lifecycle, optionsApplier));
    }

然后调用Glide.buildFileDescriptorModelLoader()方法,这个方法和上面Glide.buildStreamModelLoader()方法流程类似,只是把resourceClass由InputStream.class换成了ParcelFileDescriptor

    public static <T> ModelLoader<T, ParcelFileDescriptor> buildFileDescriptorModelLoader(Class<T> modelClass,
            Context context) {
        return buildModelLoader(modelClass, ParcelFileDescriptor.class, context);
    }

所以,简短截说,这里最终返回的是一个FileDescriptorStringLoader对象

返回RequestManager.loadGeneric()方法,最后的apply(),就是把参数里new出来的DrawableTypeRequest对象返回出来,而DrawableTypeRequest对象的构造方法,就是对属性的简单赋值

而后一路返回,返回到RequestManager.load(string)方法

    public DrawableTypeRequest<String> load(String string) {
        return (DrawableTypeRequest<String>) fromString().load(string);
    }

我们刚刚过完的是fromString()方法,获取到了一个DrawableTypeRequest对象,接下来执行的,是它的load(string)方法。但DrawableTypeRequest没有实现load(string)方法,所以执行的是其父类DrawableRequestBuilder的load(string)方法

    @Override
    public DrawableRequestBuilder<ModelType> load(ModelType model) {
        super.load(model);
        return this;
    }

再往父类里面走,是GenericRequestBuilder.load()方法

    public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> load(ModelType model) {
        this.model = model;
        isModelSet = true;
        return this;
    }

原来就是把字符串赋值给了model属性


这样RequestManager.load(string)方法也执行完了,主要是根据String获取了一个StreamStringLoader和FileDescriptorStringLoader,并且把它们俩和String的内容存到一个DrawableTypeRequest对象中,最后把DrawableTypeRequest对象返回。接下来,我们执行最后一步:into(ImageView)


DrawableTypeRequest#into(ImageView)

实际上,DrawableTypeRequest没有实现into()方法,调用的还是父类DrawableRequestBuilder的into()方法

    @Override
    public Target<GlideDrawable> into(ImageView view) {
        return super.into(view);
    }

继续向父类追溯,到了GenericRequestBuilder.into(view)方法

    public Target<TranscodeType> into(ImageView view) {
        Util.assertMainThread();
        .. // view的判空

        if (!isTransformationSet && view.getScaleType() != null) {
            switch (view.getScaleType()) {
                case CENTER_CROP:
                    applyCenterCrop();
                    break;
                case FIT_CENTER:
                case FIT_START:
                case FIT_END: // 默认是applyFitCenter,把glide里的drawableFitCenter对象赋值给DrawableRequestBuilder对象
                    applyFitCenter();
                    break;
                //$CASES-OMITTED$
                default:
                    // Do nothing.
            }
        }

        return into(glide.buildImageViewTarget(view, transcodeClass));
    }

主要是是执行里面的into(target)方法,不过先执行的是glide.buildImageViewTarget()方法,代码如下

    <R> Target<R> buildImageViewTarget(ImageView imageView, Class<R> transcodedClass) {
        return imageViewTargetFactory.buildTarget(imageView, transcodedClass);
    }

调用了ImageViewTargetFactory.buildTarget()方法,代码如下

public class ImageViewTargetFactory {

    @SuppressWarnings("unchecked")
    public <Z> Target<Z> buildTarget(ImageView view, Class<Z> clazz) { // 传入的clazz是GlideDrawable
        if (GlideDrawable.class.isAssignableFrom(clazz)) {
            return (Target<Z>) new GlideDrawableImageViewTarget(view); // 进入这个分支,new一个GlideDrawableImageViewTarget对象
        } else if (Bitmap.class.equals(clazz)) {
            return (Target<Z>) new BitmapImageViewTarget(view);
        } else if (Drawable.class.isAssignableFrom(clazz)) {
            return (Target<Z>) new DrawableImageViewTarget(view);
        } else {
            .. // 异常
        }
    }
}

获取一个GlideDrawableImageViewTarget对象后,返回到GenericRequestBuilder.into(view)方法中,立马进入GenericRequestBuilder.into(target)方法里

    public <Y extends Target<TranscodeType>> Y into(Y target) {
        Util.assertMainThread();
        .. // 异常检测

        Request previous = target.getRequest(); // 第一次是null

        if (previous != null) { // 取消之前的request
            previous.clear();
            requestTracker.removeRequest(previous);
            previous.recycle();
        }

        Request request = buildRequest(target); // 构造一个request(此处是GenericRequest对象),默认直接调用GenericRequestBuilder.obtainRequest()方法,进行一些属性的赋值,最主要的是把glide.engine和model(也就是我们的图片网址)赋值给request中
        target.setRequest(request); // 把request做为标签,和GlideDrawableImageViewTarget联系起来
        lifecycle.addListener(target); // 并且GlideDrawableImageViewTarget也是一个FragmentActivityLifecycle的监听器
        requestTracker.runRequest(request); // 添加到RequestTracker的请求队列中

        return target;
    }

这样,就已经构造好了请求,并且添加到了请求队列中。

那么这个请求何时发起呢?在最开始Glide.with(activity)方法中,我们曾把一个RequestManagerFragment和我们的activty绑定到了一起,所以在我们的activity生命周期执行到onStart()的时候,RequestManagerFragment也会执行到onStart(),代码如下

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

我们知道lifeCycle是一个ActivityFragmentLifecycle对象,它的onStart()方法的代码如下

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

遍历lifecycle的监听器,经过前面的分析,我们知道监听器有三个:GlideDrawableImageViewTarget、RequestManager和NullConnectivityMonitor


GlideDrawableImageViewTarget的onStart()方法代码如下

    @Override
    public void onStart() {
        if (resource != null) { // resource是null
            resource.start();
        }
    }

由于我们还没发请求,所以resource是null,这个方法就成了摆设

最主要的,就是是RequestManager的onStart()方法,代码如下

    @Override
    public void onStart() {
        // onStart might not be called because this object may be created after the fragment/activity's onStart method.
        resumeRequests();
    }

调用了resumeRequest()方法,代码如下

    public void resumeRequests() {
        Util.assertMainThread(); // 确保是主线程
        requestTracker.resumeRequests();
    }

又调用了requestTracker的resumeRequests()方法,再跟

    public void resumeRequests() {
        isPaused = false;
        for (Request request : Util.getSnapshot(requests)) {
            if (!request.isComplete() && !request.isCancelled() && !request.isRunning()) {
                request.begin();
            }
        }
        pendingRequests.clear();
    }

遍历request队列,依次执行没有完成取消也不在运行着的请求。我们的请求是GenericRequest,它的begin()方法源码如下

    @Override
    public void begin() {
        startTime = LogTime.getLogTime();
        .. // model的判空

        status = Status.WAITING_FOR_SIZE;
        if (Util.isValidDimensions(overrideWidth, overrideHeight)) { // 两个参数默认都是-1,所以判断不成立
            onSizeReady(overrideWidth, overrideHeight);
        } else {
            target.getSize(this); // 进入这个分支,获取GlideDrawableIamgeViewTarget的尺寸,其实就是ImageView的尺寸
        }

        if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {
            target.onLoadStarted(getPlaceholderDrawable()); // 在加载之前,先设置一个占位符,不过默认是null,一片空白
        }
        .. // 日志
    }

可以看到,在三个方法中,主要是调用了target.getSize()方法,代码如下

    @Override
    public void getSize(SizeReadyCallback cb) {
        sizeDeterminer.getSize(cb);
    }
调用的是sizeDeterminer.getSize(cb)方法,代码如下
        public void getSize(SizeReadyCallback cb) {
            int currentWidth = getViewWidthOrParam();
            int currentHeight = getViewHeightOrParam();
            if (isSizeValid(currentWidth) && isSizeValid(currentHeight)) {
                cb.onSizeReady(currentWidth, currentHeight);
            } else {
                .. 
            }
        }

以宽度为例,调用了getViewWidthOrParam()方法,代码如下

        private int getViewWidthOrParam() {
            final LayoutParams layoutParams = view.getLayoutParams();
            if (isSizeValid(view.getWidth())) { // width > 0 或 width == WRAP_CONTENT(-2)才为真
                return view.getWidth();
            } else if (layoutParams != null) { //所以我这儿走的是第二个分支,返回屏幕的宽度
                return getSizeForParam(layoutParams.width, false /*isHeight*/);
            } else {
                return PENDING_SIZE;
            }
        }

获取尺寸后,返回sizeDeterminer.getSize(cb)方法,调用cb.onSizeReady()方法,传入尺寸。这里的回调,就是GenericRequest对象,它的onSizeReady()方法代码如下

    @Override
    public void onSizeReady(int width, int height) {
        .. // 日志 + 状态

        width = Math.round(sizeMultiplier * width); // sizeMultiplier是图片的缩放倍数,默认是1
        height = Math.round(sizeMultiplier * height);

        ModelLoader<A, T> modelLoader = loadProvider.getModelLoader(); // 获取的是ImageVideoModelLoader
        final DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(model, width, height); // 获取的是ImageVideoModelLoader.ImageVideoFethcer

        if (dataFetcher == null) {
            .. // 异常处理
        }
        ResourceTranscoder<Z, R> transcoder = loadProvider.getTranscoder(); // 转码器,支持gif
        .. // 日志
        loadedFromMemoryCache = true;
        loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
                priority, isMemoryCacheable, diskCacheStrategy, this);
        loadedFromMemoryCache = resource != null;
        .. 日志
    }

然后主要是调用了engine.load()方法,代码如下

    public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,
            DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder,
            Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
        Util.assertMainThread();
        long startTime = LogTime.getLogTime();

        final String id = fetcher.getId(); // fetcher的id就是图片的网址
        EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
                loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
                transcoder, loadProvider.getSourceEncoder());

        .. // 尝试从缓存中读取图片

        .. // 尝试从资源中读取图片

        .. // 如果有EngineJob处理这个请求,就返回一个LoadStatus

        EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable); // 处理请求的engineJob
        DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,
                transcoder, diskCacheProvider, diskCacheStrategy, priority); // 解码job
        EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority); // 主要的图片获取和解码工作有EngineRunnable完成
        jobs.put(key, engineJob); // 存入engineJob
        engineJob.addCallback(cb); // 添加缓存,这里是GenericRequest
        engineJob.start(runnable); // 开启线程

        .. // 日志
        return new LoadStatus(cb, engineJob); // 把回调和engineJob存入LoadStatus的属性里
    }

可见,获取图片数据并解码,就在EngineRunnable的run()方法中,代码如下

    @Override
    public void run() {
        if (isCancelled) {
            return;
        }

        Exception exception = null;
        Resource<?> resource = null;
        try {
            resource = decode();
        } catch (Exception e) {
            .. // 异常
        }

        if (isCancelled) {
            // 回收resource
        }

        if (resource == null) {
            onLoadFailed(exception);
        } else {
            onLoadComplete(resource);
        }
    }

调用了decode()方法,代码如下

    private Resource<?> decode() throws Exception {
        if (isDecodingFromCache()) { // 试着从缓存中读取解码
            return decodeFromCache();
        } else {
            return decodeFromSource();
        }
    }

我们看decodeFromSource(),因为第一次缓存里不可能有东西

    private Resource<?> decodeFromSource() throws Exception {
        return decodeJob.decodeFromSource();
    }

调用了decodeJob.decodeFromSource()

    public Resource<Z> decodeFromSource() throws Exception {
        Resource<T> decoded = decodeSource();
        return transformEncodeAndTranscode(decoded);
    }

进入decodeSource()

    private Resource<T> decodeSource() throws Exception {
        Resource<T> decoded = null;
        try {
            long startTime = LogTime.getLogTime();
            final A data = fetcher.loadData(priority); // 此处的fetcher是ImageVideoFetcher,优先级是普通
            .. // 日志+状态
            decoded = decodeFromSourceData(data);
        } finally {
            fetcher.cleanup();
        }
        return decoded;
    }

进入ImageVideoFetcher.loadData()中

        @Override
        public ImageVideoWrapper loadData(Priority priority) throws Exception {
            InputStream is = null;
            if (streamFetcher != null) {
                try {
                    is = streamFetcher.loadData(priority); // 这里的steamFethcer就是HttpUrlFetcher
                } catch (Exception e) {
                    .. //异常
                }
            }
            .. // 试着从fileDescriptor中读取
            return new ImageVideoWrapper(is, fileDescriptor);
        }

进入HttpUrlFetcher.loadData()方法

    @Override
    public InputStream loadData(Priority priority) throws Exception {
        return loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/, glideUrl.getHeaders());
    }

获取URL和headers后,进入loadDataWithRedirects()方法

    private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl, Map<String, String> headers)
            throws IOException {
        if (redirects >= MAXIMUM_REDIRECTS) { // 重连次数检测
            .. // 异常
        } else {
            .. // url异常检测
        }
        urlConnection = connectionFactory.build(url); // 构建url链接(其实就是url.openConnection())并设置属性
        for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
          urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
        }
        urlConnection.setConnectTimeout(2500);
        urlConnection.setReadTimeout(2500);
        urlConnection.setUseCaches(false);
        urlConnection.setDoInput(true);

        // Connect explicitly to avoid errors in decoders if connection fails.
        urlConnection.connect(); // url开始连接
        if (isCancelled) {
            return null;
        }
        final int statusCode = urlConnection.getResponseCode(); // 状态码
        if (statusCode / 100 == 2) {
            return getStreamForSuccessfulRequest(urlConnection); // 获取输入流
        } else if (statusCode / 100 == 3) {
            .. // 重连
            return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
        } else {
            .. // 抛出异常
        }
    }

成功获取url的输入流后,就是ImageVideoBitmapDecoder的解码工作了,这里直接忽略掉。然后获取Resource(这里就是BitmapDrawableResource),回到EngineRunnable.run()方法,一切顺利的话,会走到onLoadCompelete()方法中,传入resource,调用EngineJob.onResourceReady(reource)方法,设置resource,给主线程的handler发送compelete消息

    @Override
    public void onResourceReady(final Resource<?> resource) {
        this.resource = resource;
        MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
    }

主线程handler是在回调里处理消息的

    private static class MainThreadCallback implements Handler.Callback {

        @Override
        public boolean handleMessage(Message message) {
            if (MSG_COMPLETE == message.what || MSG_EXCEPTION == message.what) {
                EngineJob job = (EngineJob) message.obj;
                if (MSG_COMPLETE == message.what) {
                    job.handleResultOnMainThread();
                } else {
                    job.handleExceptionOnMainThread();
                }
                return true;
            }

            return false;
        }
    }

成功的话,调用的是EngineJob.handleResultOnMainThread()方法,在主线程渲染UI,代码如下

    private void handleResultOnMainThread() {
        .. 
        engineResource = engineResourceFactory.build(resource, isCacheable); // 通过resource获取engineResource,其实就是两个属性的赋值
        hasResource = true;

        // Hold on to resource for duration of request so we don't recycle it in the middle of notifying if it
        // synchronously released by one of the callbacks.
        engineResource.acquire(); // 确保是在主线程
        listener.onEngineJobComplete(key, engineResource); // listener是Engine,从jobs中移除这个请求

        for (ResourceCallback cb : cbs) {
            if (!isInIgnoredCallbacks(cb)) {
                engineResource.acquire();
                cb.onResourceReady(engineResource); // 这里的回调是GenericRequest
            }
        }
        // Our request is complete, so we can release the resource.
        engineResource.release();
    }

主要是调用了GenericRequest.onResourceReady(resource)方法,代码如下

    @Override
    public void onResourceReady(Resource<?> resource) {
        if (resource == null) {
            .. // 异常
        }

        Object received = resource.get(); // 获取resource中的图片对象,这里是GlideDrawable,继承自BitmapDrawable
        if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
            .. // 异常
        }

        if (!canSetResource()) {
            .. // 不能设置就释放
        }

        onResourceReady(resource, (R) received);
    }

调用了onResourceReady(resource, received)方法,代码如下

    private void onResourceReady(Resource<?> resource, R result) {
        // We must call isFirstReadyResource before setting status.
        boolean isFirstResource = isFirstReadyResource();
        status = Status.COMPLETE;
        this.resource = resource;

        if (requestListener == null || !requestListener.onResourceReady(result, model, target, loadedFromMemoryCache,
                isFirstResource)) {
            GlideAnimation<R> animation = animationFactory.build(loadedFromMemoryCache, isFirstResource);
            target.onResourceReady(result, animation);
        }

        ..

        .. // 日志
    }

主要是调用了target.onResourceReady()方法,这里的target是GlideDrawableImageViewTarget,不过调用的是其父类ImageViewTarget的这个方法

    @Override
    public void onResourceReady(Z resource, GlideAnimation<? super Z> glideAnimation) {
        if (glideAnimation == null || !glideAnimation.animate(resource, this)) {
            setResource(resource);
        }
    }

不在动画中,就调用setResource()方法,这个方法由子类实现,GlideDrawableImageViewTarget的实现如下

    @Override
    protected void setResource(GlideDrawable resource) {
        view.setImageDrawable(resource);
    }

至此,一张图片加载完毕


结语

Glide使用和Picasso差不多,但由于功能上的不一样,源码复杂度也大相径庭。最亮眼的就是Glide把图片的加载同activity的生命周期关联在了一起。

猜你喜欢

转载自blog.csdn.net/qq_37475168/article/details/80847012