Fresco源码解析:初始化过程(二)

本文承接Fresco源码解析: 初始化过程(一)

从ImagePipelineConfig的构造函数开始,再贴一遍代码

 private ImagePipelineConfig(Builder builder) {
    // We have to build experiments before the rest
    //目前处于实验状态的一些选项,变动很大,官方建议不要修改这些选项的默认值
    mImagePipelineExperiments = builder.mExperimentsBuilder.build();
    //bitmap内存缓存参数的提供者,以MemoryCacheParams类的形式封装
    mBitmapMemoryCacheParamsSupplier = builder.mBitmapMemoryCacheParamsSupplier == null ?
            new DefaultBitmapMemoryCacheParamsSupplier((ActivityManager) builder.mContext.getSystemService(Context.ACTIVITY_SERVICE)) :
            builder.mBitmapMemoryCacheParamsSupplier;
    //内存回收策略
    mBitmapMemoryCacheTrimStrategy = builder.mBitmapMemoryCacheTrimStrategy == null ? new BitmapMemoryCacheTrimStrategy() :
            builder.mBitmapMemoryCacheTrimStrategy;
   // bitmap的配置参数,Bitmap.Config默认使用ARGB_8888,相对于Glid更好内存
    mBitmapConfig = builder.mBitmapConfig == null ? Bitmap.Config.ARGB_8888 : builder.mBitmapConfig;
    //生成缓存key的工厂,如果不想使用默认的key生成方法,可以自定义这个factory
    mCacheKeyFactory = builder.mCacheKeyFactory == null ? DefaultCacheKeyFactory.getInstance() : builder.mCacheKeyFactory;
    mContext = Preconditions.checkNotNull(builder.mContext);
    //文件缓存的工厂
    mFileCacheFactory = builder.mFileCacheFactory == null ? new DiskStorageCacheFactory(new DynamicDefaultDiskStorageFactory()) :
        builder.mFileCacheFactory;
    mDownsampleEnabled = builder.mDownsampleEnabled;
    //未解码的内存缓存参数 
    mEncodedMemoryCacheParamsSupplier = builder.mEncodedMemoryCacheParamsSupplier == null ? new DefaultEncodedMemoryCacheParamsSupplier() :
            builder.mEncodedMemoryCacheParamsSupplier;
            //图片缓存统计跟踪工具
    mImageCacheStatsTracker = builder.mImageCacheStatsTracker == null ? NoOpImageCacheStatsTracker.getInstance() : builder.mImageCacheStatsTracker;
    //图片解码工具
    mImageDecoder = builder.mImageDecoder;
    //是否开启预加载的开关提供者,默认是开启
    mIsPrefetchEnabledSupplier = builder.mIsPrefetchEnabledSupplier == null ?
            new Supplier<Boolean>() {
              @Override
              public Boolean get() {
                return true;
              }
            } :
            builder.mIsPrefetchEnabledSupplier;
//主硬盘缓存的配置参数
mMainDiskCacheConfig = builder.mMainDiskCacheConfig == null ? getDefaultMainDiskCacheConfig(builder.mContext) :
            builder.mMainDiskCacheConfig;
     //那些需要监听系统内存变化的对象,就需要添加到这个对象中
    mMemoryTrimmableRegistry = builder.mMemoryTrimmableRegistry == null ? NoOpMemoryTrimmableRegistry.getInstance() :
            builder.mMemoryTrimmableRegistry;
     //网络数据获取的工具,默认使用HttpUrlConnectionNetworkFetcher,也可以自己定义
    mNetworkFetcher = builder.mNetworkFetcher == null ?  new HttpUrlConnectionNetworkFetcher() : builder.mNetworkFetcher;
    //根据不同android版本生成不同的bitmap的工厂,主要是bitmap内存存储位置,5.0以前存储在ashmem,5.0以后存在java heap中,默认为空
    mPlatformBitmapFactory = builder.mPlatformBitmapFactory;
    //生产各种池的工厂
    mPoolFactory = builder.mPoolFactory == null ? new PoolFactory(PoolConfig.newBuilder().build()) : builder.mPoolFactory;
    //渐进式加载的配置参数
    mProgressiveJpegConfig = builder.mProgressiveJpegConfig == null ? new SimpleProgressiveJpegConfig() :builder.mProgressiveJpegConfig;
    //监听request过程中的各种事件
    mRequestListeners = builder.mRequestListeners == null ? new HashSet<RequestListener>() : builder.mRequestListeners;
    mResizeAndRotateEnabledForNetwork = builder.mResizeAndRotateEnabledForNetwork;
    //小图硬盘缓存的配置参数,对应于mMainDiskCacheConfig 
    mSmallImageDiskCacheConfig = builder.mSmallImageDiskCacheConfig == null ? mMainDiskCacheConfig :builder.mSmallImageDiskCacheConfig;
    //图片解码器的配置参数
    mImageDecoderConfig = builder.mImageDecoderConfig;
    // Below this comment can't be built in alphabetical order, because of dependencies
   //允许访问线程池的最大线程数
    int numCpuBoundThreads = mPoolFactory.getFlexByteArrayPoolMaxNumThreads();
    //线程池
    mExecutorSupplier = builder.mExecutorSupplier == null ? new DefaultExecutorSupplier(numCpuBoundThreads) : builder.mExecutorSupplier;
    // Here we manage the WebpBitmapFactory implementation if any
    //在不支持webp的android版本上(4.0开始支持简单的webp,4.2.1后全面支持)支持解码webp图片的工厂,默认为null
    WebpBitmapFactory webpBitmapFactory = mImagePipelineExperiments.getWebpBitmapFactory();
    if (webpBitmapFactory != null) {
      BitmapCreator bitmapCreator = new HoneycombBitmapCreator(getPoolFactory());
      setWebpBitmapFactory(webpBitmapFactory, mImagePipelineExperiments, bitmapCreator);
    } else {
      // We check using introspection only if the experiment is enabled
      if (mImagePipelineExperiments.isWebpSupportEnabled() &&
          WebpSupportStatus.sIsWebpSupportRequired) {
        webpBitmapFactory = WebpSupportStatus.loadWebpBitmapFactoryIfExists();
        if (webpBitmapFactory != null) {
          BitmapCreator bitmapCreator = new HoneycombBitmapCreator(getPoolFactory());
          setWebpBitmapFactory(webpBitmapFactory, mImagePipelineExperiments, bitmapCreator);
        }
      }
    }
  }
 //目前处于实验状态的一些选项,变动很大,官方建议不要修改这些选项的默认值
    mImagePipelineExperiments = builder.mExperimentsBuilder.build();

上面这行代码主要构造了一个ImagePipelineExperiments对象,类介绍如下:

Encapsulates additional elements of the ImagePipelineConfig which are currently in an >experimental state.
These options may often change or disappear altogether and it is not recommended to change >their values from their defaults.

大致意思就是说这个类里包含了一些正在处于实验阶段的ImagePipelineConfig 中的元素,这些元素经常在变或者消失,所以不建议去改变他们的默认值。我这里也不再详细的说明,有兴趣可以看源码或者官方文档。

 //bitmap内存缓存参数的提供者,以MemoryCacheParams类的形式封装
    mBitmapMemoryCacheParamsSupplier = builder.mBitmapMemoryCacheParamsSupplier == null ?
            new DefaultBitmapMemoryCacheParamsSupplier((ActivityManager) 

上面代码是初始化bitmap内存缓存的参数提供者,默认使用DefaultBitmapMemoryCacheParamsSupplier,我们看下DefaultBitmapMemoryCacheParamsSupplier的代码,主要看get()方法:

public class DefaultBitmapMemoryCacheParamsSupplier implements Supplier<MemoryCacheParams> {
  private static final int MAX_CACHE_ENTRIES = 256;
  private static final int MAX_EVICTION_QUEUE_SIZE = Integer.MAX_VALUE;
  private static final int MAX_EVICTION_QUEUE_ENTRIES = Integer.MAX_VALUE;
  private static final int MAX_CACHE_ENTRY_SIZE = Integer.MAX_VALUE;

  private final ActivityManager mActivityManager;

  public DefaultBitmapMemoryCacheParamsSupplier(ActivityManager activityManager) {
    mActivityManager = activityManager;
  }

  @Override
  public MemoryCacheParams get() {
    return new MemoryCacheParams(
        getMaxCacheSize(),
        MAX_CACHE_ENTRIES,
        MAX_EVICTION_QUEUE_SIZE,
        MAX_EVICTION_QUEUE_ENTRIES,
        MAX_CACHE_ENTRY_SIZE);
  }

  private int getMaxCacheSize() {
    final int maxMemory = Math.min(mActivityManager.getMemoryClass() * ByteConstants.MB, Integer.MAX_VALUE);
    if (maxMemory < 32 * ByteConstants.MB) {
      return 4 * ByteConstants.MB;
    } else if (maxMemory < 64 * ByteConstants.MB) {
      return 6 * ByteConstants.MB;
    } else {
      // We don't want to use more ashmem on Gingerbread for now, since it doesn't respond well to
      // native memory pressure (doesn't throw exceptions, crashes app, crashes phone)
      if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
        return 8 * ByteConstants.MB;
      } else {
        return maxMemory / 4;
      }
    }
  }
} 

get()方法中新建了一个MemoryCacheParams对象,这个类很简单,就是指定了缓存的一些参数,比如最多几条数据等,源码如下

public class MemoryCacheParams {

  public final int maxCacheSize;
  public final int maxCacheEntries;
  public final int maxEvictionQueueSize;
  public final int maxEvictionQueueEntries;
  public final int maxCacheEntrySize;

  /**
   * Pass arguments to control the cache's behavior in the constructor.
   *
   * @param maxCacheSize The maximum size of the cache, in bytes.
   * @param maxCacheEntries The maximum number of items that can live in the cache.
   * @param maxEvictionQueueSize The eviction queue is an area of memory that stores items ready
   *                             for eviction but have not yet been deleted. This is the maximum
   *                             size of that queue in bytes.
   * @param maxEvictionQueueEntries The maximum number of entries in the eviction queue.
   * @param maxCacheEntrySize The maximum size of a single cache entry.
   */
  public MemoryCacheParams(
      int maxCacheSize,
      int maxCacheEntries,
      int maxEvictionQueueSize,
      int maxEvictionQueueEntries,
      int maxCacheEntrySize) {
    this.maxCacheSize = maxCacheSize;
    this.maxCacheEntries = maxCacheEntries;
    this.maxEvictionQueueSize = maxEvictionQueueSize;
    this.maxEvictionQueueEntries = maxEvictionQueueEntries;
    this.maxCacheEntrySize = maxCacheEntrySize;
  }
}

我们看第一个参数也就是maxCacheSize,它指定了最大能缓存的内存总量,以byte为单位。这个值的获取是通过getMaxCacheSize()方法。逻辑如下:

通过使用getMemoryClass来确定当前应用可以开辟的最大heapsize,如果最大heapsize小于32M就设置为4M,如果大于32M小于64M就设置为6M。如果大于64M,则在HONEYCOMB(3.0)之前的机器上设置为8M,之后的机器设置为最大值除以4

关于为什么在3.0之前的机器上要做特殊处理,官网的解释如下:

We don’t want to use more ashmem on Gingerbread for now, since it doesn’t respond well to
native memory pressure (doesn’t throw exceptions, crashes app, crashes phone)

也就是说在3.0以前的机器上,系统对ashmem的内存管理并不是做的很好,所以不想使用太多的ashmem内存。
其他几项数值都是取Integer.MAX_VALUE

//bitmap内存缓存回收策略
mBitmapMemoryCacheTrimStrategy = builder.mBitmapMemoryCacheTrimStrategy == null ? new BitmapMemoryCacheTrimStrategy() :builder.mBitmapMemoryCacheTrimStrategy;

内存回收策略类,实现了CountingMemoryCache.CacheTrimStrategy接口,这个接口只有一个方法getTrimRatio(MemoryTrimType trimType),此方法的参数是MemoryTrimType类型,这个类是一个枚举类型,里面定义了一些内存回收的类型,每个类型有一个建议的内存回收比例,源代码如下:

/**
 * Types of memory trim.
 *
 * <p>Each type of trim will provide a suggested trim ratio.
 *
 * <p>A {@link MemoryTrimmableRegistry} implementation sends out memory trim events with this type.
 */
public enum MemoryTrimType {

  /** The application is approaching the device-specific Java heap limit. */
  OnCloseToDalvikHeapLimit(0.5),

  /** The system as a whole is running out of memory, and this application is in the foreground. */
  OnSystemLowMemoryWhileAppInForeground(0.5),

  /** The system as a whole is running out of memory, and this application is in the background. */
  OnSystemLowMemoryWhileAppInBackground(1),

  /** This app is moving into the background, usually because the user navigated to another app. */
  OnAppBackgrounded(1);

  private double mSuggestedTrimRatio;

  private MemoryTrimType(double suggestedTrimRatio) {
    mSuggestedTrimRatio = suggestedTrimRatio;
  }

  /** Get the recommended percentage by which to trim the cache on receiving this event. */
  public double getSuggestedTrimRatio () {
    return mSuggestedTrimRatio;
  }
}

所以getTrimRatio方法就是根据不同的回收类型,返回不同的回收比例,CacheTrimStrategy的默认的实现类是BitmapMemoryCacheTrimStrategy,源代码如下:

/**
 * CountingMemoryCache eviction strategy appropriate for bitmap caches.
 *
 * <p>If run on KitKat or below, then this TrimStrategy behaves exactly as
 * NativeMemoryCacheTrimStrategy. If run on Lollipop, then BitmapMemoryCacheTrimStrategy will trim
 * cache in one additional case: when OnCloseToDalvikHeapLimit trim type is received, cache's
 * eviction queue will be trimmed according to OnCloseToDalvikHeapLimit's suggested trim ratio.
 */
public class BitmapMemoryCacheTrimStrategy implements CountingMemoryCache.CacheTrimStrategy {
  private static final String TAG = "BitmapMemoryCacheTrimStrategy";

  @Override
  public double getTrimRatio(MemoryTrimType trimType) {
    switch (trimType) {
      case OnCloseToDalvikHeapLimit:
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
          return MemoryTrimType.OnCloseToDalvikHeapLimit.getSuggestedTrimRatio();
        } else {
          // On pre-lollipop versions we keep bitmaps on the native heap, so no need to trim here
          // as it wouldn't help Dalvik heap anyway.
          return 0;
        }
      case OnAppBackgrounded:
      case OnSystemLowMemoryWhileAppInForeground:
      case OnSystemLowMemoryWhileAppInBackground:
        return 1;
      default:
        FLog.wtf(TAG, "unknown trim type: %s", trimType);
        return 0;
    }
  }
}

这个类注释似乎和代码的实现有点不一样。。。先留着回头再看是否真的有问题

 //文件缓存的工厂
    mFileCacheFactory = builder.mFileCacheFactory == null ? new DiskStorageCacheFactory(new DynamicDefaultDiskStorageFactory()) :
        builder.mFileCacheFactory;

文件缓存的工厂,实现了FileCacheFactory接口,这个接口只有一个get方法,用于返回一个FileCache实例,这个FileCache就是用来管理文件缓存。这里的FileCacheFactory默认实现是DiskStorageCacheFactory,看名字就是硬盘缓存,如果有兴趣也可以用别的途径实现,database?它的构造函数需要一个实现了DiskStorageFactory接口的实例,DiskStorageFactory接口就是用来提供实现DiskStorage接口的实例的,DiskStorage接口描述如下:

Storage for files in the cache.
Responsible for maintaining state (count, size, watch file existence, reachability)

意思就是用来保存缓存的文件,并负责维护状态,比如个数,大小,文件后缀,是否可达等。里面提供了一些操作文件的方法,如图DiskStorage的一些方法。其中有一个值得注意的方法是

  /**
   * Creates a temporary resource for writing content. Split from commit()
   * in order to allow concurrent writing of cache entries.
   * This entry will not be available to cache clients until
   * commit() is called passing in the resource returned
   * from this method.
   * @param resourceId id of the resource
   * @param debugInfo helper object for debugging
   * @return the Inserter object with methods to write data, commit or cancel the insertion
   * @exception IOException on errors during this operation
   */
 Inserter insert(String resourceId, Object debugInfo)throws IOException;

从方法描述可以看出,这个方法不是直接把缓存文件放进缓存,中间会有一个缓存文件,而用户要通过操作方法返回的Inserter 接口来实现真正的commit。具体的实现可以参考DynamicDefaultDiskStorageFactory。

//未解码的内存缓存参数提供器 
mEncodedMemoryCacheParamsSupplier = builder.mEncodedMemoryCacheParamsSupplier == null ? new DefaultEncodedMemoryCacheParamsSupplier() :builder.mEncodedMemoryCacheParamsSupplier;

图片刚从网上下载之后是没有被解码的,Fresco对这部分的数据也会缓存在内存中,这个缓存的一些参数参数就由DefaultEncodedMemoryCacheParamsSupplier提供,我们可以看一下它的具体实现,到底提供了哪些参数。

/**
 * Supplies {@link MemoryCacheParams} for the encoded image memory cache
 */
public class DefaultEncodedMemoryCacheParamsSupplier implements Supplier<MemoryCacheParams> {

  // We want memory cache to be bound only by its memory consumption
  private static final int MAX_CACHE_ENTRIES = Integer.MAX_VALUE;
  private static final int MAX_EVICTION_QUEUE_ENTRIES = MAX_CACHE_ENTRIES;

  @Override
  public MemoryCacheParams get() {
    final int maxCacheSize = getMaxCacheSize();
    final int maxCacheEntrySize = maxCacheSize / 8;
    return new MemoryCacheParams(
        maxCacheSize,
        MAX_CACHE_ENTRIES,
        maxCacheSize,
        MAX_EVICTION_QUEUE_ENTRIES,
        maxCacheEntrySize);
  }

  private int getMaxCacheSize() {
    final int maxMemory = (int) Math.min(Runtime.getRuntime().maxMemory(), Integer.MAX_VALUE);
    if (maxMemory < 16 * ByteConstants.MB) {
      return 1 * ByteConstants.MB;
    } else if (maxMemory < 32 * ByteConstants.MB) {
      return 2 * ByteConstants.MB;
    } else {
      return 4 * ByteConstants.MB;
    }
  }
}

可以看到,整个结构和前面提到的DefaultBitmapMemoryCacheParamsSupplier是一样的,都是实现了Supplier<MemoryCacheParams>接口,然后通过 MemoryCacheParams来封装这些参数,所以提供的参数也是一样的。

//图片缓存统计跟踪工具
mImageCacheStatsTracker = builder.mImageCacheStatsTracker == null ? NoOpImageCacheStatsTracker.getInstance() : builder.mImageCacheStatsTracker;

ImageCacheStatsTracker是一个接口,里面定义了一些回调方法,当图片缓存发生变化时(包括bitmap和EncodedImage)会回调这些方法,用户可以重写这些方法,默认的实现类NoOpImageCacheStatsTracker没有重写任何方法,这里应该属于接口的适配器设计模式,用户可以通过继承NoOpImageCacheStatsTracker类来重写自己关心的回调方法,比如有新的bitmap图片加入缓存了,会回调onBitmapCachePut()

//主硬盘缓存的配置参数
mMainDiskCacheConfig = builder.mMainDiskCacheConfig == null ? getDefaultMainDiskCacheConfig(builder.mContext) : builder.mMainDiskCacheConfig;
//小图硬盘缓存的配置参数,对应于mMainDiskCacheConfig 
mSmallImageDiskCacheConfig = builder.mSmallImageDiskCacheConfig == null ? mMainDiskCacheConfig :builder.mSmallImageDiskCacheConfig;

其中的MainDiskCacheConfig就是一般图片的缓存,平时的图片都是缓存在这里,而SmallImage是什么呢?官网文档有说明:

用一个还是两个磁盘缓存?
如果要使用2个缓存,在配置image pipeline 时调用 setMainDiskCacheConfig 和 setSmallImageDiskCacheConfig 方法即可。
大部分的应用有一个磁盘缓存就够了,但是在一些情况下,你可能需要两个缓存。比如你也许想把小文件放在一个缓存中,大文件放在另外一个文件中,这样小文件就不会因大文件的频繁变动而被从缓存中移除。
至于什么是小文件,这个由应用来区分,在创建image request, 设置 ImageType 即可:

ImageRequest request = ImageRequest.newBuilderWithSourceUri(uri)
    .setImageType(ImageType.SMALL)

如果你仅仅需要一个缓存,那么不调用setSmallImageDiskCacheConfig即可。Image pipeline 默认会使用>同一个缓存,同时ImageType也会被忽略。

也就是说只有被设置为ImageType.SMALL的图片才会存到SmallImageDiskCache,也才会使用到mSmallImageDiskCacheConfig。那这个config到底配置了哪些东西呢,当然要看源码了。在默认情况下使用的是getDefaultMainDiskCacheConfig()方法返回的实力,我们就看这个方法,源码如下:

  private static DiskCacheConfig getDefaultMainDiskCacheConfig(final Context context) {
    return DiskCacheConfig.newBuilder(context).build();
  }

是一个建造者模式,我们直接进到build()方法:

    public DiskCacheConfig build() {
      Preconditions.checkState(
          mBaseDirectoryPathSupplier != null || mContext != null,
          "Either a non-null context or a base directory path or supplier must be provided.");
      if (mBaseDirectoryPathSupplier == null && mContext != null) {
        mBaseDirectoryPathSupplier = new Supplier<File>() {
          @Override
          public File get() {
            return mContext.getApplicationContext().getCacheDir();
          }
        };
      }
      return new DiskCacheConfig(this);
    }

逻辑很简单,先检查mBaseDirectoryPathSupplier和mContext是否有一个不为空,只有要一个不为空就继续,然后如果 mBaseDirectoryPathSupplier为null,就新建一个Supplier<File>实例,从变量名字看,这个supplier就是指定了缓存文件个根目录,就是通过getCacheDir()返回的目录,最后再返回一个DiskCacheConfig实例,我们看一下这个构造函数。

  private DiskCacheConfig(Builder builder) {
    mVersion = builder.mVersion;
    mBaseDirectoryName = Preconditions.checkNotNull(builder.mBaseDirectoryName);
    mBaseDirectoryPathSupplier = Preconditions.checkNotNull(builder.mBaseDirectoryPathSupplier);
    mDefaultSizeLimit = builder.mMaxCacheSize;
    mLowDiskSpaceSizeLimit = builder.mMaxCacheSizeOnLowDiskSpace;
    mMinimumSizeLimit = builder.mMaxCacheSizeOnVeryLowDiskSpace;
    mEntryEvictionComparatorSupplier =  Preconditions.checkNotNull(builder.mEntryEvictionComparatorSupplier);
    mCacheErrorLogger = builder.mCacheErrorLogger == null ? NoOpCacheErrorLogger.getInstance() : builder.mCacheErrorLogger;
    mCacheEventListener = builder.mCacheEventListener == null ? NoOpCacheEventListener.getInstance() : builder.mCacheEventListener;
    mDiskTrimmableRegistry = builder.mDiskTrimmableRegistry == null ? NoOpDiskTrimmableRegistry.getInstance() :builder.mDiskTrimmableRegistry;
    mContext = builder.mContext;
    mIndexPopulateAtStartupEnabled = builder.mIndexPopulateAtStartupEnabled;
  }

第1行指定了config的版本,第2行指定了文件缓存的根目录文件名,默认是ImagePipelineConfigFactory.IMAGE_PIPELINE_CACHE_DIR = "imagepipeline_cache"

下面这行就是之前在build方法中指定的缓存目录路径
mBaseDirectoryPathSupplier =Preconditions.checkNotNull(builder.mBaseDirectoryPathSupplier);
所以默认的缓存目录就是data/data/xxx.xxx.xx/cache/imagepipeline_cache。
mDefaultSizeLimit = builder.mMaxCacheSize;这行指定了默认最大的缓存大小,为**40M**。
mLowDiskSpaceSizeLimit = builder.mMaxCacheSizeOnLowDiskSpace;指定了在硬盘存储偏小的情况下,缓存的最大值。
mMinimumSizeLimit = builder.mMaxCacheSizeOnVeryLowDiskSpace;这个值用于计算在设备磁盘缓存特别特别低的时候,对硬盘缓存进行回收时的比例。

mEntryEvictionComparatorSupplier =  Preconditions.checkNotNull(builder.mEntryEvictionComparatorSupplier);

指定那些需要被移除的缓存条目的排序器,默认实现是DefaultEntryEvictionComparatorSupplier,是按访问时间来排序,将最旧的移除。

mCacheErrorLogger = builder.mCacheErrorLogger == null ? NoOpCacheErrorLogger.getInstance() : builder.mCacheErrorLogger;

各种cache error的处理类,默认啥都没做。

mCacheEventListener = builder.mCacheEventListener == null ? NoOpCacheEventListener.getInstance() : builder.mCacheEventListener;

各种缓存事件的处理类,默认啥都不做。

NoOpDiskTrimmableRegistry.getInstance():builder.mDiskTrimmableRegistry;    

这个类是用来管理那些实现了DiskTrimmable借口的类,主要是当系统的硬盘空间发生变化的时候通知这些类

mIndexPopulateAtStartupEnabled = builder.mIndexPopulateAtStartupEnabled

对这个变量的作用还不是很清楚,先放着

以上就是DiskCacheConfig里面配置的一些项目

 mNetworkFetcher = builder.mNetworkFetcher == null ? new HttpUrlConnectionNetworkFetcher() : builder.mNetworkFetcher;

网络抓取的实现类,也就是真正从网上下载数据的地方,默认使用HttpUrlConnectionNetworkFetcher。

//生产各种池的工厂
mPoolFactory = builder.mPoolFactory == null ? new PoolFactory(PoolConfig.newBuilder().build()) : builder.mPoolFactory;

PoolFactory提供各种内存对象的池,比如bitmapPool,FlexByteArrayPool,NativeMemoryChunkPool等,这些pool在网络抓取,图片缓存中都会用到,这里我们简单看一下Fresco中的Pool实现原理,以BitmapPool为例:

public class BitmapPool extends BasePool<Bitmap>
public abstract class BasePool<V> implements Pool<V> 

它继承了BasePool,BasePool是一个抽象类,实现了Pool<V>接口,

public interface Pool<V> extends ResourceReleaser<V>, MemoryTrimmable

这个Pool接口又继承了ResourceReleaser和MemoryTrimmable两个接口,前者用于释放资源,后者用于在内存不足的情况下回收内存,Pool接口本身有get(int size)release(V value)两个方法。前者是用于从池中获取指定大小的内容,如果不存在就开辟,后者用于向池释放内容,如果池觉得这个内容还可以重用就先放在池里,否则就释放掉。具体的实现可以参考BitmapPool

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值