Glide源码分析

Glide是由Google开发,常用的一个图片加载框架,今天我们来分析一下源码,学习下优秀的框架。本篇文章采用的源码是
com.github.bumptech.glide:glide:4.0.0-RC0

/**
 * A singleton to present a simple static interface for building requests with
 * {@link RequestBuilder} and maintaining an {@link Engine}, {@link BitmapPool},
 * {@link com.bumptech.glide.load.engine.cache.DiskCache} and {@link MemoryCache}.
 */
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public class Glide implements ComponentCallbacks2 {
	
  private static final String DEFAULT_DISK_CACHE_DIR = "image_manager_disk_cache";//外存图片缓存文件路径
  private static final String TAG = "Glide";
  private static volatile Glide glide;//volatile防止指令重排序和可见的单例

  private final Engine engine;引擎
  private final BitmapPool bitmapPool;//位图池的接口类
  private final MemoryCache memoryCache;//内存缓存接口类
  private final BitmapPreFiller bitmapPreFiller;//位图预先填充类
  private final GlideContext glideContext;//继承于ContextWrapper类,一般用于资源类相关的操作
  private final Registry registry;//注册类,应该是一种模式的写法
  private final ArrayPool arrayPool;//注释介绍是数组池
  private final RequestManagerRetriever requestManagerRetriever;//字面翻译请求管理的寻猎犬,实现了Handler.Callback -- boolean handleMessage(Message var1);
  private final ConnectivityMonitorFactory connectivityMonitorFactory;//链接监控工厂接口类,需要实现一个build方法ConnectivityMonitor build(@NonNull Context context,@NonNull ConnectivityMonitor.ConnectivityListener listener);

  private final List<RequestManager> managers = new ArrayList<>();//一个RequestManager的列表
  private MemoryCategory memoryCategory = MemoryCategory.NORMAL;//一个内存分类的枚举,提供 LOW(0.5f), NORMAL(1f),HIGH(1.5f),括号里面是倍数。动态修改glide的可用内存


//获取照片缓存的目录路径
  @Nullable
  public static File getPhotoCacheDir(Context context) {
    return getPhotoCacheDir(context, DEFAULT_DISK_CACHE_DIR);
  }

public static File getPhotoCacheDir(Context context, String cacheName) {
    File cacheDir = context.getCacheDir();//获取app的私有缓存路径
    if (cacheDir != null) {
    	//路径非空
      File result = new File(cacheDir, cacheName);//拼装路径
      if (!result.mkdirs() && (!result.exists() || !result.isDirectory())) {
	//异常情况,不能创建目录,或者文件存在但不是个目录
        return null;
      }
      return result;
    }
    if (Log.isLoggable(TAG, Log.ERROR)) {
      Log.e(TAG, "default disk cache dir is null");
    }
    return null;
  }


//双重加锁的单例创建模式,里面的初始化方法注明被弃用,写的不好呗
public static Glide get(Context context) {
    if (glide == null) {
    
      synchronized (Glide.class) {
      //对类加锁
        if (glide == null) {
        //初始化glide
          initGlide(context);
        }
      }
    }

    return glide;
  }



//用于代码测试的两个方法
 @VisibleForTesting
  public static void init(Glide glide) {
    Glide.glide = glide;
  }

  @VisibleForTesting
  public static void tearDown() {
    glide = null;
  }



//注解表明这是一个被弃用的方法,目前大家平常用的也是Glide.with()....
  @SuppressWarnings("deprecation")
  private static void initGlide(Context context) {
  //取得全局Context, 面试题app 有多少context:   Activity +Serivce + Application
    Context applicationContext = context.getApplicationContext();

//获取注解生成的Glide模块
    GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
    //生成一个空列表
    List<GlideModule> manifestModules = Collections.emptyList();
    if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
    //注解生成的模块为空,或者描述文件解析开启。下面就会从解析文件中去解析那个模块
      manifestModules = new ManifestParser(applicationContext).parse();
    }

    if (annotationGeneratedModule != null
        && !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
//注解生成的模块不为空,且之外的模块类不为空
      Set<Class<?>> excludedModuleClasses =
          annotationGeneratedModule.getExcludedModuleClasses();
          //注解之外的模块类集合
      for (Iterator<GlideModule> iterator = manifestModules.iterator(); iterator.hasNext();) {
      //遍历描述文件模块类,
        GlideModule current = iterator.next();
        if (!excludedModuleClasses.contains(current.getClass())) {
        //假如不包含就跳过
          continue;
        }
        //假如包含了,就删除掉。应该是两边不能有重复的。
        if (Log.isLoggable(TAG, Log.DEBUG)) {
          Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);
        }
        iterator.remove();
      }
    }

    if (Log.isLoggable(TAG, Log.DEBUG)) {
    //打印在描述文件中发现的类模块
      for (GlideModule glideModule : manifestModules) {
        Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
      }
    }

//请求管理工厂,尝试取注解生成模块的。
    RequestManagerRetriever.RequestManagerFactory factory =
        annotationGeneratedModule != null
            ? annotationGeneratedModule.getRequestManagerFactory() : null;
           
           //Glide builder模式,设置请求管理工厂
    GlideBuilder builder = new GlideBuilder()
        .setRequestManagerFactory(factory);
    for (GlideModule module : manifestModules) {
    	//遍历描述文件中的模块,产生作用在建造者模式中
      module.applyOptions(applicationContext, builder);
    }
    if (annotationGeneratedModule != null) {
    //注解生成模块也产生作用
      annotationGeneratedModule.applyOptions(applicationContext, builder);
    }
    //建造开始。。。。
    glide = builder.build(applicationContext);
    for (GlideModule module : manifestModules) {
    //描述文件模块注册组件
      module.registerComponents(applicationContext, glide.registry);
    }
    if (annotationGeneratedModule != null) {
    //注解生成模块注册到组件。
     annotationGeneratedModule.registerComponents(applicationContext, glide.registry);
    }
  }




//生成AppGlideModule ,虽然废弃了,但是本着一行代码不放过
  @Nullable
  @SuppressWarnings({"unchecked", "deprecation"})
  private static GeneratedAppGlideModule getAnnotationGeneratedGlideModules() {
    GeneratedAppGlideModule result = null;
    try {
    //反射com.bumptech.glide.GeneratedAppGlideModuleImpl类,创建一个对象
      Class<GeneratedAppGlideModule> clazz =
          (Class<GeneratedAppGlideModule>)
              Class.forName("com.bumptech.glide.GeneratedAppGlideModuleImpl");
      result = clazz.newInstance();
    } catch (ClassNotFoundException e) {
      if (Log.isLoggable(TAG, Log.WARN)) {
	//通过注解生成实现类,让上面的代码去反射生成实例
        Log.w(TAG, "Failed to find GeneratedAppGlideModule. You should include an"
            + " annotationProcessor compile dependency on com.github.bumptech.glide:glide:compiler"
            + " in your application and a @GlideModule annotated AppGlideModule implementation or"
            + " LibraryGlideModules will be silently ignored");
      }
    } catch (InstantiationException e) {
    //实例化失败,让你自己别瞎整。老老实实用注解
      throw new IllegalStateException("GeneratedAppGlideModuleImpl is implemented incorrectly."
          + " If you've manually implemented this class, remove your implementation. The Annotation"
          + " processor will generate a correct implementation.", e);
    } catch (IllegalAccessException e) {
    //同上
      throw new IllegalStateException("GeneratedAppGlideModuleImpl is implemented incorrectly."
          + " If you've manually implemented this class, remove your implementation. The Annotation"
          + " processor will generate a correct implementation.", e);
    }
    return result;
  }


//构造函数
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
  Glide(
      Context context,
      Engine engine,
      MemoryCache memoryCache,
      BitmapPool bitmapPool,
      ArrayPool arrayPool,
      RequestManagerRetriever requestManagerRetriever,
      ConnectivityMonitorFactory connectivityMonitorFactory,
      int logLevel,
      RequestOptions defaultRequestOptions) {
    this.engine = engine;
    this.bitmapPool = bitmapPool;
    this.arrayPool = arrayPool;
    this.memoryCache = memoryCache;
    this.requestManagerRetriever = requestManagerRetriever;
    this.connectivityMonitorFactory = connectivityMonitorFactory;

//图像的上采样(up-sampling)和下采样(down-sampling),下采样就是缩放,就是让图片符合合适的显示大小
//解码格式 DecodeFormat 是个枚举类,里面就两种类型1. PREFER_ARGB_8888 四通道4字节 2.PREFER_RGB_565  3通道 2字节。 默认是第一种
    DecodeFormat decodeFormat = defaultRequestOptions.getOptions().get(Downsampler.DECODE_FORMAT);
    //位图提前填充类,构造参数,内存缓存,位图池,解析格式
    bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat);

    final Resources resources = context.getResources();

    //注册管理类,对于注册这个概念,应该说可动态的用不同的hi实现类去调整改变实现,基本是用了反射的方法,工程师应该是在抽象出图片加载的各个环节,竟然可配置的更改实现。
    registry = new Registry();
    //先注册默认的图片头解码类
    registry.register(new DefaultImageHeaderParser());

//下采样类生成
    Downsampler downsampler = new Downsampler(registry.getImageHeaderParsers(),
        resources.getDisplayMetrics(), bitmapPool, arrayPool);
//字节数组GIf解码类
    ByteBufferGifDecoder byteBufferGifDecoder =
        new ByteBufferGifDecoder(context, registry.getImageHeaderParsers(), bitmapPool, arrayPool);

//下面代码会很长,注册编码期,用右边的入参对象编码成左边的类型
    registry.register(ByteBuffer.class, new ByteBufferEncoder())
        .register(InputStream.class, new StreamEncoder(arrayPool))
        /* Bitmaps */
        //下面又是解码注册,把第一个入参类型通过第三个入参对象解码成第二个入参类型
        .append(ByteBuffer.class, Bitmap.class,
            new ByteBufferBitmapDecoder(downsampler))
        .append(InputStream.class, Bitmap.class,
            new StreamBitmapDecoder(downsampler, arrayPool))
        .append(ParcelFileDescriptor.class, Bitmap.class, new VideoBitmapDecoder(bitmapPool))
        .register(Bitmap.class, new BitmapEncoder())
        /* GlideBitmapDrawables */
        .append(ByteBuffer.class, BitmapDrawable.class,
            new BitmapDrawableDecoder<>(resources, bitmapPool,
                new ByteBufferBitmapDecoder(downsampler)))
        .append(InputStream.class, BitmapDrawable.class,
            new BitmapDrawableDecoder<>(resources, bitmapPool,
                new StreamBitmapDecoder(downsampler, arrayPool)))
        .append(ParcelFileDescriptor.class, BitmapDrawable.class,
            new BitmapDrawableDecoder<>(resources, bitmapPool, new VideoBitmapDecoder(bitmapPool)))
        .register(BitmapDrawable.class, new BitmapDrawableEncoder(bitmapPool, new BitmapEncoder()))
        /* GIFs */
        .prepend(InputStream.class, GifDrawable.class,
            new StreamGifDecoder(registry.getImageHeaderParsers(), byteBufferGifDecoder, arrayPool))
        .prepend(ByteBuffer.class, GifDrawable.class, byteBufferGifDecoder)
        .register(GifDrawable.class, new GifDrawableEncoder())
        /* GIF Frames */
        .append(GifDecoder.class, GifDecoder.class, new UnitModelLoader.Factory<GifDecoder>())
        .append(GifDecoder.class, Bitmap.class, new GifFrameResourceDecoder(bitmapPool))
        /* Files */
        //下面是一些工厂注册
        .register(new ByteBufferRewinder.Factory())
        .append(File.class, ByteBuffer.class, new ByteBufferFileLoader.Factory())
        .append(File.class, InputStream.class, new FileLoader.StreamFactory())
        .append(File.class, File.class, new FileDecoder())
        .append(File.class, ParcelFileDescriptor.class, new FileLoader.FileDescriptorFactory())
        .append(File.class, File.class, new UnitModelLoader.Factory<File>())
        /* Models */
        .register(new InputStreamRewinder.Factory(arrayPool))
        .append(int.class, InputStream.class, new ResourceLoader.StreamFactory(resources))
        .append(
                int.class,
                ParcelFileDescriptor.class,
                new ResourceLoader.FileDescriptorFactory(resources))
        .append(Integer.class, InputStream.class, new ResourceLoader.StreamFactory(resources))
        .append(
                Integer.class,
                ParcelFileDescriptor.class,
                new ResourceLoader.FileDescriptorFactory(resources))
        .append(String.class, InputStream.class, new DataUrlLoader.StreamFactory())
        .append(String.class, InputStream.class, new StringLoader.StreamFactory())
        .append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory())
        .append(Uri.class, InputStream.class, new HttpUriLoader.Factory())
        .append(Uri.class, InputStream.class, new AssetUriLoader.StreamFactory(context.getAssets()))
        .append(
                Uri.class,
                ParcelFileDescriptor.class,
                new AssetUriLoader.FileDescriptorFactory(context.getAssets()))
        .append(Uri.class, InputStream.class, new MediaStoreImageThumbLoader.Factory(context))
        .append(Uri.class, InputStream.class, new MediaStoreVideoThumbLoader.Factory(context))
        .append(
            Uri.class,
             InputStream.class,
             new UriLoader.StreamFactory(context.getContentResolver()))
        .append(Uri.class, ParcelFileDescriptor.class,
             new UriLoader.FileDescriptorFactory(context.getContentResolver()))
        .append(Uri.class, InputStream.class, new UrlUriLoader.StreamFactory())
        .append(URL.class, InputStream.class, new UrlLoader.StreamFactory())
        .append(Uri.class, File.class, new MediaStoreFileLoader.Factory(context))
        .append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())
        .append(byte[].class, ByteBuffer.class, new ByteArrayLoader.ByteBufferFactory())
        .append(byte[].class, InputStream.class, new ByteArrayLoader.StreamFactory())
        /* Transcoders */
        .register(Bitmap.class, BitmapDrawable.class,
            new BitmapDrawableTranscoder(resources, bitmapPool))
        .register(Bitmap.class, byte[].class, new BitmapBytesTranscoder())
        .register(GifDrawable.class, byte[].class, new GifDrawableBytesTranscoder());

    ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
//生成GlideContext
    glideContext = new GlideContext(context, registry, imageViewTargetFactory,
        defaultRequestOptions, engine, this, logLevel);
  }

类上面的英文注释说明: Glide 采用单例模式,提供一个简单的静态接口,为了创建请求,和维护一个Engine, BitmapPool,DiskCache, MemoryCahe.

Glide 实现了一个接口ComponentCallbacks2

public interface ComponentCallbacks2 extends ComponentCallbacks {
    int TRIM_MEMORY_BACKGROUND = 40;
    int TRIM_MEMORY_COMPLETE = 80;
    int TRIM_MEMORY_MODERATE = 60;
    int TRIM_MEMORY_RUNNING_CRITICAL = 15;
    int TRIM_MEMORY_RUNNING_LOW = 10;
    int TRIM_MEMORY_RUNNING_MODERATE = 5;
    int TRIM_MEMORY_UI_HIDDEN = 20;

    void onTrimMemory(int var1);
}


public interface ComponentCallbacks {
    void onConfigurationChanged(Configuration var1);

    void onLowMemory();
}


以上两个接口来源于package android.content; 应该是遵循安卓系统的内存回收规则,一般情况下,我们如果能遵循这个机制,达到相应不同程度的内存清理,可以最大程度上保证我们app存活和运行稳定。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值