Android图片加载框架Fresco分析(一)

作为Android开发者,虽然不是大牛,但也接触了很多图片加载框架,因为手机上最难处理最占内存的往往也就是图片,如果图片处理不好,很容易引起程序崩溃。到目前为止我接触过很多种图片加载框架,其中主要有:UniversalImageLoader,Picasso,Glide,Fresco。
Fresco是Facebook最新推出的一款用于Android应用中展示图片的强大图片库,可以从网络、本地存储和本地资源中加载图片。其中的Drawees可以显示占位符,直到图片加载完成。而当图片从屏幕上消失时,会自动释放内存。由于目前项目中使用到了Fresco,所以针对Fresco做一下源码分析。

1.功能介绍

Fresco类似ImageLoader和Picasoo一样,操作起来都比较简单,几行代码就可以开始使用了。可以简单的在xml里使用SimpleDraweeView配置一些属性。在代码中使用SimpleDraweeViewsetImageURI方法来进行图片的加载。

Fresco有很大的优点,Fresco的中文文档中说的就很明白,主要优点有:

  1. 能够通过Drawees模块让不再显示在屏幕上的图片及时地释放内存和空间。
  2. 能够渐进式加载图片。这也是其他图片加载控件所没有的功能。
  3. 支持加载Gif图,支持WebP格式
  4. 缩放或者旋转图片,圆形圆角图片等等

    2.总体设计

Fresco总体上也是MVC模式,但是其中包含了很多的设计模式,之后会慢慢叙述。在源代码中。

  • DraweeView就相当于View层,负责图片展示以及各种loading,加载效果。
  • DraweeController负责接洽View层的展示,每一个view会有一个mDraweeHolder,holder将view中的各种除了展示的操作解耦出来,分而治之。holder中又包含一个controller。controller则负责与下一层hierarchy的连接操作。
  • DraweeHierarchy相当于M层,用于下载和转换等,维护最终绘制和呈现的Drawable对象。

3.Fresco简单使用

使用起来很简单,在Android Studio里面的build.gradle文件中配置好对fresco的引用。

dependencies {
compile 'com.facebook.fresco:fresco:0.3.0+'
}

之后要在Application类中进行初始化操作:

Fresco.initialize(this, FrescoConfig.getImagePipelineConfig(this));

FrescoConfig中可以设置一些缓存空间大小,缓存图片地址,以及设置几级缓存。MemoryCacheParams可以对内存进行配置:

//内存配置
final MemoryCacheParams bitmapCacheParams = new MemoryCacheParams(
FrescoConfig.MAX_MEMORY_CACHE_SIZE, // 内存缓存中总图片的最大大小,以字节为单位。
Integer.MAX_VALUE,                     // 内存缓存中图片的最大数量。
FrescoConfig.MAX_MEMORY_CACHE_SIZE, // 内存缓存中准备清除但尚未被删除的总图片的最大大小,以字节为单位。
Integer.MAX_VALUE,                     // 内存缓存中准备清除的总图片的最大数量。
Integer.MAX_VALUE);                    // 内存缓存中单个图片的最大大小。

要想使用刚才设置的内存缓存配置需要,使用得到一个Supplier才能设置成功。

//修改内存图片缓存数量,空间策略(这个方式有点恶心)
Supplier<MemoryCacheParams> mSupplierMemoryCacheParams = new Supplier<MemoryCacheParams>() {
    @Override
    public MemoryCacheParams get() {
        return bitmapCacheParams;
    }
};

还可以对小图片和默认图片进行磁盘的配置:

public static final String IMAGE_PIPELINE_CACHE_DIR = "/rodriguez/image";//默认图所放路径的文件夹名
public static final int MAX_DISK_CACHE_VERYLOW_SIZE = 10 * ByteConstants.MB;//默认图极低磁盘空间缓存的最大值
public static final int MAX_DISK_CACHE_LOW_SIZE = 30 * ByteConstants.MB;//默认图低磁盘空间缓存的最大值
public static final int MAX_DISK_CACHE_SIZE = 50 * ByteConstants.MB;//默认图磁盘缓存的最大值
//默认图片的磁盘配置
DiskCacheConfig diskCacheConfig = DiskCacheConfig.newBuilder()
        .setBaseDirectoryPath(Environment.getExternalStorageDirectory().getAbsoluteFile())//缓存图片基路径
        .setBaseDirectoryName(IMAGE_PIPELINE_CACHE_DIR)//文件夹名
//            .setCacheErrorLogger(cacheErrorLogger)//日志记录器用于日志错误的缓存。
//            .setCacheEventListener(cacheEventListener)//缓存事件侦听器。
//            .setDiskTrimmableRegistry(diskTrimmableRegistry)//类将包含一个注册表的缓存减少磁盘空间的环境。
        .setMaxCacheSize(FrescoConfig.MAX_DISK_CACHE_SIZE)//默认缓存的最大大小。
        .setMaxCacheSizeOnLowDiskSpace(MAX_DISK_CACHE_LOW_SIZE)//缓存的最大大小,使用设备时低磁盘空间。
        .setMaxCacheSizeOnVeryLowDiskSpace(MAX_DISK_CACHE_VERYLOW_SIZE)//缓存的最大大小,当设备极低磁盘空间
//            .setVersion(version)
        .build();

最后一步便是将之前设置的config应用到Fresco中。需要使用到ImagePipelineConfig.Builder,builder中可以对很多属性进行配置,比如图片解码库,是否旋转图片,是否渐进式加载等等。需要的同学可以去官方文档中查询相关设置。

//缓存图片配置
ImagePipelineConfig.Builder configBuilder = ImagePipelineConfig.newBuilder(context)
        .setBitmapMemoryCacheParamsSupplier(mSupplierMemoryCacheParams)//内存缓存配置(一级缓存,已解码的图片)
        .setMainDiskCacheConfig(diskCacheConfig)//磁盘缓存配置(总,三级缓存)
        .setSmallImageDiskCacheConfig(diskSmallCacheConfig)//磁盘缓存配置(小图片,可选~三级缓存的小图优化缓存)
        ;

然后将得到的builder设置到之前的initialize代码中,便可以应用。经过这番操作,初始化配置过程基本上算已经完成。

要使用Fresco加载图片。也是特别简单的。在xml文件中添加上相应的view,在设置一些需要的fresco参数。

<com.facebook.drawee.view.SimpleDraweeView
        xmlns:fresco="http://schemas.android.com/apk/res-auto"
        android:id="@+id/goods_image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        fresco:progressBarImage="@drawable/loading_circle_gray"
        fresco:progressBarAutoRotateInterval="@integer/default_loading_duration"
        fresco:failureImage="@drawable/image_default_bg"/>

记住一定要在当前view或者根view中添加xmlns:fresco…这句。当前代码中也只是简单的对loading view和错误图片做了设置。

之后便是最简单也最需要的加载图片了。

imageView.setImageURI(imgUri);

一句话就可以将操作交给Fresco,自己就可以做其他的事情了。