Glide加载图片流程(Part One)

由于项目的需要,这几天对Glide的执行过程做了简单的了解,希望对想了解Glide基本用法的朋友能有所帮助。

注意

  • 此系列博客基于Glide V3.7.0版本源码

  • 这里假设朋友们能够在Android Studio中正确引入Glide相关的依赖,如果有不懂的朋友,请参考官方文档引入依赖。


为了让朋友们尽快的了解Glide加载图片的流程,我们就从最简单的方式入手。请看如下代码:

ImageView fullscreenView = (ImageView) findViewById(R.id.fullscreen_view);
String imageUrl = "http://image.url.com";
Glide.with(this)
     .load(imageUrl)
     .into(fullscreenView);

代码清单1-1

使用Glide加载图片就是这么简单!!!

然而,简单的背后往往隐藏了太多的未知数,那么现在我们就来看看这几行简单代码背后究竟隐藏了哪些奇妙的东西。现在就和博主一起开启Glide的学习之旅吧 :)

一、with(this)

在上述代码清单1-1中,我是在FragmentActivity子类中调用了Glide的with方法,SO这里的this即是指FragmentActivity的子类实例。我们点击查看其源码,如下:

public static RequestManager with(FragmentActivity activity) {
    RequestManagerRetriever retriever = RequestManagerRetriever.get();
    return retriever.get(activity);
}

首先获取一个RequestManagerRetriever实例,通过该实例得到RequestManager对象。我们现在进入RequestManagerRetriever#get(FragmentActivity)方法中来具体看看RequestManager的获取过程:

 public RequestManager get(FragmentActivity activity) {
        if (Util.isOnBackgroundThread()) {
            return get(activity.getApplicationContext());
        } else {
            assertNotDestroyed(activity);
            FragmentManager fm = activity.getSupportFragmentManager();
            return supportFragmentGet(activity, fm);
        }
    }

我们只考虑常规情况下使用的场景(不考虑缓存等情况,后文与此相同),由上面的代码,我们很容易定位到supportFragmentGet方法:

 RequestManager supportFragmentGet(Context context, FragmentManager fm) {
        SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);
        RequestManager requestManager = current.getRequestManager();
        if (requestManager == null) {
            requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
            current.setRequestManager(requestManager);
        }
        return requestManager;
    }

由于我们是初次调用Glide加载图片,所以这里会创建一个新的RequestManager实例,并存入SupportRequestManagerFragmentcurrent实例中。传入RequestManager对象中的LifecycleRequestManagerTreeNode我们后面再说。这里需要注意的是,在创建RequestManager对象时,默认创建了一个RequestTracker对象和OptionsApplier对象,以及我们的Glide对象。

我们进入到RequestManager的构造函数中,定位到glide实例的获取过程:

  RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,
            RequestTracker requestTracker, ConnectivityMonitorFactory factory) {
        this.context = context.getApplicationContext();
        this.lifecycle = lifecycle;
        this.treeNode = treeNode;
        this.requestTracker = requestTracker;
        this.glide = Glide.get(context);
        this.optionsApplier = new OptionsApplier();

        //省略其它无关代码
        ...........................
        ...........................
    }

在上述代码中,我们顺藤摸瓜,来到Glide类的get方法中:

 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的实例过程中,我们看到Glide会从AndroidManifest.xml文件中查询我们注册的GlideModule。同时将GlideBuilderGlide的实例传入我们注册的GlideModule的对应方法中。由此我们可以了解到,如果想预先控制Glide的一些行为,可以在我们的GlideModuleapplyOtionsregisterComponents方法中做控制。

接下来我们继续查看GlideBuildercreateGlide方法,直接定位到方法的最后一行:

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

好了,重头戏该上演了,我们来看看Glide类的构造函数:

Glide(Engine engine, MemoryCache memoryCache, BitmapPool bitmapPool, Context context, DecodeFormat decodeFormat) {
        this.engine = engine;
        this.bitmapPool = bitmapPool;
        this.memoryCache = memoryCache;
        this.decodeFormat = decodeFormat;
        loaderFactory = new GenericLoaderFactory(context);
        mainHandler = new Handler(Looper.getMainLooper());
        bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat);

        dataLoadProviderRegistry = new DataLoadProviderRegistry();

        StreamBitmapDataLoadProvider streamBitmapLoadProvider =
                new StreamBitmapDataLoadProvider(bitmapPool, decodeFormat);
        dataLoadProviderRegistry.register(InputStream.class, Bitmap.class, streamBitmapLoadProvider);

        FileDescriptorBitmapDataLoadProvider fileDescriptorLoadProvider =
                new FileDescriptorBitmapDataLoadProvider(bitmapPool, decodeFormat);
        dataLoadProviderRegistry.register(ParcelFileDescriptor.class, Bitmap.class, fileDescriptorLoadProvider);

        ImageVideoDataLoadProvider imageVideoDataLoadProvider =
                new ImageVideoDataLoadProvider(streamBitmapLoadProvider, fileDescriptorLoadProvider);
        dataLoadProviderRegistry.register(ImageVideoWrapper.class, Bitmap.class, imageVideoDataLoadProvider);

        GifDrawableLoadProvider gifDrawableLoadProvider =
                new GifDrawableLoadProvider(context, bitmapPool);
        dataLoadProviderRegistry.register(InputStream.class, GifDrawable.class, gifDrawableLoadProvider);

        dataLoadProviderRegistry.register(ImageVideoWrapper.class, GifBitmapWrapper.class,
                new ImageVideoGifDrawableLoadProvider(imageVideoDataLoadProvider, gifDrawableLoadProvider, bitmapPool));

        dataLoadProviderRegistry.register(InputStream.class, File.class, new StreamFileDataLoadProvider());

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

        transcoderRegistry.register(Bitmap.class, GlideBitmapDrawable.class,
                new GlideBitmapDrawableTranscoder(context.getResources(), bitmapPool));
        transcoderRegistry.register(GifBitmapWrapper.class, GlideDrawable.class,
                new GifBitmapWrapperDrawableTranscoder(
                        new GlideBitmapDrawableTranscoder(context.getResources(), bitmapPool)));

        bitmapCenterCrop = new CenterCrop(bitmapPool);
        drawableCenterCrop = new GifBitmapWrapperTransformation(bitmapPool, bitmapCenterCrop);

        bitmapFitCenter = new FitCenter(bitmapPool);
        drawableFitCenter = new GifBitmapWrapperTransformation(bitmapPool, bitmapFitCenter);
    }

这个方法相对比较长,但是理解起来较为简单。主要就是注册一些DataLoadProviderModelLoaderfactory以及几个Transcoder。为了更直观的理解和查询,我将它们罗列成下面三张表:(PS:这三张表对于理解Glide的加载流程很重要

表1-1 ModelType到DataType的映射表

ID ModelClass ResourceClass DataLoaderFactory
1 File ParcelFileDescriptor FileDescriptorFileLoader.Factory
2 File InputStream StreamFileLoader.Factory
3 int ParcelFileDescriptor FileDescriptorResourceLoader.Factory
4 int InputStream StreamResourceLoader.Factory
5 Integer ParcelFileDescriptor FileDescriptorResourceLoader.Factory
6 Integer InputStream StreamResourceLoader.Factory
7 String ParcelFileDescriptor FileDescriptorStringLoader.Factory
8 String InputStream StreamStringLoader.Factory
9 Uri ParcelFileDescriptor FileDescriptorUriLoader.Factory
10 Uri InputStream StreamUriLoader.Factory
11 URL InputStream StreamUrlLoader.Factory
12 GlideUrl InputStream HttpUrlGlideUrlLoader
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值