欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-14 19:32:04
...

背景

我在安卓开发学习之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的使用及源码阅读


源码阅读

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

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

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的生命周期关联在了一起。

相关标签: Glide