Android开发Android开发经验谈Android技术知识

【Glide】- 源码分析

2020-03-18  本文已影响0人  拔萝卜占坑

简介

Glide由Google推出的图片加载框架,支持多种图片格式,同类的还有picassofresco。picasso功能没有Glide强大,也不支持gif加载,fresco是Facebook公司推出的框架。

添加glide

// glide
implementation 'com.github.bumptech.glide:glide:4.10.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0'

实例

Glide.with(targetImageView.getContext())
      .load(headerUrl)
      .into(targetImageView);

Glide初始化

在调用with方法的时候,如果Glide没有初始化,那么会先进行初始化,创建Glide实例。

Glide编译

在编译过程中,Glide注解程序会生成GeneratedAppGlideModuleImpl和GeneratedRequestManagerFactory两个类来帮助Glide的初始化。

创建GeneratedAppGlideModuleImpl对象

通过创建GeneratedAppGlideModuleImpl对象来获取初始化和配置信息实例,并组装到glide实例中。

创建Glide初始化配置实例

自定义ConfigGlideModule,并继承于AppGlideModule抽象类,通过“GlideModule”注解或者在AndroidManifest配置来指定。

  1. 注解方式
    @com.bumptech.glide.annotation.GlideModule
     public class ConfigGlideModule extends AppGlideModule {
         @Override
         public boolean isManifestParsingEnabled() {return false;}
    
         @Override
         public void applyOptions(Context context, GlideBuilder builder) {super.applyOptions(context, builder);}
     }
    
  2. 清单文件配置
    <application>
        <meta-data
            android:name="xx.xx.xx.ConfigGlideModule"
            android:value="GlideModule" />
    </application>
    
with过程

创建初始化Glide实例,调用with方法对glide进行初始化,with()方法可以接收Context、Activity,Fragment类型参数。如果调用的地方不在Activity,Fragment中,可以获取当前应用程序的ApplicationContext,传入到with()方法中。如果传入的是Activity或者Fragment的实例,那么当这个Activity或Fragment被销毁的时候,图片加载也会停止。如果传入的是ApplicationContext,那么只有当应用程序被杀掉的时候,图片加载才会停止。

Glide类中存在下面两个变量。

  private static volatile Glide glide;
  private static volatile boolean isInitializing;

如果glide是null,才会去创建glide对象,如果isInitializing是true,代表glide正在初始化,这时候如果再次初始化,是直接会抛异常的,所以在多线程使用环境中一定要注意。

load过程

into过程

glide需要工作在主线程,否则直接抛异常。

请求执行引擎

这部分讲解真正的从网络端获取数据,并处理的逻辑

获取缓存数据

如果缓存存在,者直接返回缓存数据,不在执行请求,否则运行请求。

创建请求任务

请求任务也进行了缓存,如果缓存里面存在该请求任务,这不会创建新的请求任务,只添加执行回调。具体,请自己看源码。

    EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {
      current.addCallback(cb, callbackExecutor);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Added to existing load", startTime, key);
      }
      return new LoadStatus(cb, current);
    }

如果缓存没有该任务,者会创建EngineJob和DecodeJob两个任务实例,然后缓存,执行任务

jobs.put(key, engineJob);
engineJob.addCallback(cb, callbackExecutor);
engineJob.start(decodeJob);
执行请求任务
engineJob.start(decodeJob);

调用这个方法后会执行DecodeJob中的run方法,然后执行 runWrapped()

  private void runWrapped() {
    switch (runReason) {
      case INITIALIZE:
        stage = getNextStage(Stage.INITIALIZE);
        currentGenerator = getNextGenerator();
        runGenerators();
        break;
      case SWITCH_TO_SOURCE_SERVICE:
        runGenerators();
        break;
      case DECODE_DATA:
        decodeFromRetrievedData();
        break;
      default:
        throw new IllegalStateException("Unrecognized run reason: " + runReason);
    }
  }

根据不同的运行类型,执行不同的流程

总结

glide加载大体流程就这样,最后面数据解析和回调写得有点模糊,自己看了一下代码,有点多,自己可以去跟踪一下,看一下大体处理逻辑。下一篇将写一篇用法总结,如果对里面的原理不关心的,可以阅读我下一篇文章。

上一篇 下一篇

猜你喜欢

热点阅读