/**
     * Sets disc cache for images.<br>
     * Default value - {@link com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache
     * UnlimitedDiscCache}. Cache directory is defined by <b> {@link
     * com.nostra13.universalimageloader.utils.StorageUtils#getCacheDirectory(Context)
     * StorageUtils.getCacheDirectory(Context)}.<br>
     */
    public Builder discCache(DiscCacheAware discCache) {
      if (discCacheSize > 0) L.w(WARNING_OVERLAP_DISC_CACHE_SIZE);
      if (discCacheFileCount > 0) L.w(WARNING_OVERLAP_DISC_CACHE_FILE_COUNT);
      if (discCacheFileNameGenerator != null) L.w(WARNING_OVERLAP_DISC_CACHE_FILE_NAME_GENERATOR);

      this.discCache = discCache;
      return this;
    }
    /**
     * Sets maximum disc cache size for images (in bytes).<br>
     * By default: disc cache is unlimited.<br>
     * <b>NOTE:</b> If you use this method then {@link
     * com.nostra13.universalimageloader.cache.disc.impl.TotalSizeLimitedDiscCache
     * TotalSizeLimitedDiscCache} will be used as disc cache. You can use {@link
     * #discCache(DiscCacheAware)} method for introduction your own implementation of {@link
     * DiscCacheAware}
     */
    public Builder discCacheSize(int maxCacheSize) {
      if (maxCacheSize <= 0)
        throw new IllegalArgumentException("maxCacheSize must be a positive number");
      if (discCache != null) L.w(WARNING_DISC_CACHE_ALREADY_SET);
      if (discCacheFileCount > 0) L.w(WARNING_OVERLAP_DISC_CACHE_FILE_COUNT);

      this.discCacheSize = maxCacheSize;
      return this;
    }
    /**
     * Sets maximum file count in disc cache directory.<br>
     * By default: disc cache is unlimited.<br>
     * <b>NOTE:</b> If you use this method then {@link
     * com.nostra13.universalimageloader.cache.disc.impl.FileCountLimitedDiscCache
     * FileCountLimitedDiscCache} will be used as disc cache. You can use {@link
     * #discCache(DiscCacheAware)} method for introduction your own implementation of {@link
     * DiscCacheAware}
     */
    public Builder discCacheFileCount(int maxFileCount) {
      if (maxFileCount <= 0)
        throw new IllegalArgumentException("maxFileCount must be a positive number");
      if (discCache != null) L.w(WARNING_DISC_CACHE_ALREADY_SET);
      if (discCacheSize > 0) L.w(WARNING_OVERLAP_DISC_CACHE_SIZE);

      this.discCacheSize = 0;
      this.discCacheFileCount = maxFileCount;
      return this;
    }
    /**
     * 设置本地文件系统缓存器 Sets disk cache for images.<br>
     * Default value - {@link com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache
     * UnlimitedDiskCache}. Cache directory is defined by {@link
     * com.nostra13.universalimageloader.utils.StorageUtils#getCacheDirectory(Context)
     * StorageUtils.getCacheDirectory(Context)}.<br>
     * <br>
     * <b>NOTE:</b> If you set custom disk cache then following configuration option will not be
     * considered:
     *
     * <ul>
     *   <li>{@link #diskCacheSize(int)}
     *   <li>{@link #diskCacheFileCount(int)}
     *   <li>{@link #diskCacheFileNameGenerator(FileNameGenerator)}
     * </ul>
     */
    public Builder diskCache(DiskCache diskCache) {
      if (diskCacheSize > 0 || diskCacheFileCount > 0) {
        L.w(WARNING_OVERLAP_DISK_CACHE_PARAMS);
      }
      if (diskCacheFileNameGenerator != null) {
        L.w(WARNING_OVERLAP_DISK_CACHE_NAME_GENERATOR);
      }

      this.diskCache = diskCache;
      return this;
    }
 public diskCacheSize diskCache(DiskCache diskcache)
 {
     if (diskCacheSize > 0L || diskCacheFileCount > 0)
     {
         L.w("diskCache(), diskCacheSize() and diskCacheFileCount calls overlap each other", new Object[0]);
     }
     if (diskCacheFileNameGenerator != null)
     {
         L.w("diskCache() and diskCacheFileNameGenerator() calls overlap each other", new Object[0]);
     }
     diskCache = diskcache;
     return this;
 }
 /**
  * Initializes ImageLoader instance with configuration.<br>
  * If configurations was set before ( {@link #isInited()} == true) then this method does nothing.
  * <br>
  * To force initialization with new configuration you should {@linkplain #destroy() destroy
  * ImageLoader} at first.
  *
  * @param configuration {@linkplain ImageLoaderConfiguration ImageLoader configuration}
  * @throws IllegalArgumentException if <b>configuration</b> parameter is null
  */
 public synchronized void init(
     ImageLoaderConfiguration configuration, ImageTokenCallback tokenCallback) {
   if (configuration == null) {
     throw new IllegalArgumentException(ERROR_INIT_CONFIG_WITH_NULL);
   }
   this.tokenCallback = tokenCallback;
   if (this.configuration == null) {
     L.d(LOG_INIT_CONFIG);
     engine = new ImageLoaderEngine(configuration);
     this.configuration = configuration;
   } else {
     L.w(WARNING_RE_INIT_CONFIG);
   }
 }
  private Bitmap tryLoadBitmap() {
    DiscCacheAware discCache = configuration.discCache;
    File imageFile = discCache.get(uri);

    Bitmap bitmap = null;
    try {
      // Try to load image from disc cache
      if (imageFile.exists()) {
        log(LOG_LOAD_IMAGE_FROM_DISC_CACHE, memoryCacheKey);

        Bitmap b = decodeImage(imageFile.toURI());
        if (b != null) {
          return b;
        }
      }

      // Load image from Web
      log(LOG_LOAD_IMAGE_FROM_INTERNET, memoryCacheKey);

      URI imageUriForDecoding;
      if (options.isCacheOnDisc()) {
        log(LOG_CACHE_IMAGE_ON_DISC, memoryCacheKey);

        saveImageOnDisc(imageFile);
        discCache.put(uri, imageFile);
        imageUriForDecoding = imageFile.toURI();
      } else {
        imageUriForDecoding = new URI(uri);
      }

      bitmap = decodeImage(imageUriForDecoding);
      if (bitmap == null) {
        fireImageLoadingFailedEvent(FailReason.IO_ERROR);
      }
    } catch (IOException e) {
      L.e(e);
      fireImageLoadingFailedEvent(FailReason.IO_ERROR);
      if (imageFile.exists()) {
        imageFile.delete();
      }
    } catch (OutOfMemoryError e) {
      L.e(e);
      fireImageLoadingFailedEvent(FailReason.OUT_OF_MEMORY);
    } catch (Throwable e) {
      L.e(e);
      fireImageLoadingFailedEvent(FailReason.UNKNOWN);
    }
    return bitmap;
  }
 /**
  * {@linkplain #stop() Stops ImageLoader} and clears current configuration. <br>
  * You can {@linkplain #init(ImageLoaderConfiguration) init} ImageLoader with new configuration
  * after calling this method.
  */
 public void destroy() {
   if (configuration != null) L.d(LOG_DESTROY);
   stop();
   configuration.diskCache.close();
   engine = null;
   configuration = null;
 }
 private static File getExternalCacheDir(Context context) {
   File dataDir = new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data");
   File appCacheDir = new File(new File(dataDir, context.getPackageName()), "cache");
   if (!appCacheDir.exists()) {
     if (!appCacheDir.mkdirs()) {
       L.w("Unable to create external cache directory");
       return null;
     }
     try {
       new File(appCacheDir, ".nomedia").createNewFile();
     } catch (IOException e) {
       L.i("Can't create \".nomedia\" file in application external cache directory");
     }
   }
   return appCacheDir;
 }
  /**
   * ImageLoader参数配置构造器 把构建者中的数据 对全局变量初始化
   *
   * @param builder 构建信息对象
   */
  private ImageLoaderConfiguration(final Builder builder) {
    resources = builder.context.getResources();
    maxImageWidthForMemoryCache = builder.maxImageWidthForMemoryCache;
    maxImageHeightForMemoryCache = builder.maxImageHeightForMemoryCache;
    maxImageWidthForDiskCache = builder.maxImageWidthForDiskCache;
    maxImageHeightForDiskCache = builder.maxImageHeightForDiskCache;
    processorForDiskCache = builder.processorForDiskCache;
    taskExecutor = builder.taskExecutor;
    taskExecutorForCachedImages = builder.taskExecutorForCachedImages;
    threadPoolSize = builder.threadPoolSize;
    threadPriority = builder.threadPriority;
    tasksProcessingType = builder.tasksProcessingType;
    diskCache = builder.diskCache;
    memoryCache = builder.memoryCache;
    defaultDisplayImageOptions = builder.defaultDisplayImageOptions;
    downloader = builder.downloader;
    decoder = builder.decoder;

    customExecutor = builder.customExecutor;
    customExecutorForCachedImages = builder.customExecutorForCachedImages;

    networkDeniedDownloader = new NetworkDeniedImageDownloader(downloader);
    slowNetworkDownloader = new SlowNetworkImageDownloader(downloader);

    L.writeDebugLogs(builder.writeLogs);
  }
  private Bitmap decodeWithOOMHandling(URI imageUri) throws IOException {
    Bitmap result = null;
    ImageDecoder decoder = new ImageDecoder(imageUri, downloader, options);
    decoder.setLoggingEnabled(loggingEnabled);
    for (int attempt = 1; attempt <= ATTEMPT_COUNT_TO_DECODE_BITMAP; attempt++) {
      try {
        ViewScaleType viewScaleType = ViewScaleType.fromImageView(imageView);
        result = decoder.decode(targetSize, options.getImageScaleType(), viewScaleType);
      } catch (OutOfMemoryError e) {
        L.e(e);

        switch (attempt) {
          case 1:
            System.gc();
            break;
          case 2:
            configuration.memoryCache.clear();
            System.gc();
            break;
          case 3:
            throw e;
        }
        // Wait some time while GC is working
        SystemClock.sleep(attempt * 1000);
        continue;
      }
      break;
    }
    return result;
  }
 /**
  * @param cacheDir Directory for file caching. <b>Important:</b> Specify separate folder for
  *     cached files. It's needed for right cache limit work.
  * @param fileNameGenerator Name generator for cached files
  * @param maxCacheSize Maximum cache directory size (in bytes). If cache size exceeds this limit
  *     then file with the most oldest last usage date will be deleted.
  */
 public TotalSizeLimitedDiscCache(
     File cacheDir, FileNameGenerator fileNameGenerator, int maxCacheSize) {
   super(cacheDir, fileNameGenerator, maxCacheSize);
   if (maxCacheSize < MIN_NORMAL_CACHE_SIZE) {
     L.w("You set too small disc cache size (less than %1$d Mb)", MIN_NORMAL_CACHE_SIZE_IN_MB);
   }
 }
  private Bitmap tryLoadBitmap() throws TaskCancelledException {
    File imageFile = getImageFileInDiscCache();

    Bitmap bitmap = null;
    try {
      String cacheFileUri = Scheme.FILE.wrap(imageFile.getAbsolutePath());
      if (imageFile.exists()) {
        log(LOG_LOAD_IMAGE_FROM_DISC_CACHE);
        loadedFrom = LoadedFrom.DISC_CACHE;

        checkTaskNotActual();
        bitmap = decodeImage(cacheFileUri);
      }
      if (bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
        log(LOG_LOAD_IMAGE_FROM_NETWORK);
        loadedFrom = LoadedFrom.NETWORK;

        String imageUriForDecoding =
            options.isCacheOnDisc() && tryCacheImageOnDisc(imageFile) ? cacheFileUri : uri;

        checkTaskNotActual();
        bitmap = decodeImage(imageUriForDecoding);

        if (bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
          fireFailEvent(FailType.DECODING_ERROR, null);
        }
      }
    } catch (IllegalStateException e) {
      fireFailEvent(FailType.NETWORK_DENIED, null);
    } catch (TaskCancelledException e) {
      throw e;
    } catch (IOException e) {
      L.e(e);
      fireFailEvent(FailType.IO_ERROR, e);
      if (imageFile.exists()) {
        imageFile.delete();
      }
    } catch (OutOfMemoryError e) {
      L.e(e);
      fireFailEvent(FailType.OUT_OF_MEMORY, e);
    } catch (Throwable e) {
      L.e(e);
      fireFailEvent(FailType.UNKNOWN, e);
    }
    return bitmap;
  }
    /**
     * 设置图片显示线程池线程数量 Sets thread pool size for image display tasks.<br>
     * Default value - {@link #DEFAULT_THREAD_POOL_SIZE this}
     */
    public Builder threadPoolSize(int threadPoolSize) {
      if (taskExecutor != null || taskExecutorForCachedImages != null) {
        L.w(WARNING_OVERLAP_EXECUTOR);
      }

      this.threadPoolSize = threadPoolSize;
      return this;
    }
    /**
     * Sets maximum memory cache size for {@link android.graphics.Bitmap bitmaps} (in bytes).<br>
     * Default value - {@link #DEFAULT_MEMORY_CACHE_SIZE this}<br>
     * <b>NOTE:</b> If you use this method then {@link
     * com.nostra13.universalimageloader.cache.memory.impl.UsingFreqLimitedMemoryCache
     * UsingFreqLimitedCache} will be used as memory cache. You can use {@link
     * #memoryCache(MemoryCacheAware)} method for introduction your own implementation of {@link
     * MemoryCacheAware}.
     */
    public Builder memoryCacheSize(int memoryCacheSize) {
      if (memoryCacheSize <= 0)
        throw new IllegalArgumentException("memoryCacheSize must be a positive number");
      if (memoryCache != null) L.w(WARNING_MEMORY_CACHE_ALREADY_SET);

      this.memoryCacheSize = memoryCacheSize;
      return this;
    }
    /**
     * 设置图片内存缓存器 Sets memory cache for {@link android.graphics.Bitmap bitmaps}.<br>
     * Default value - {@link com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache
     * LruMemoryCache} with limited memory cache size (size = 1/8 of available app memory)<br>
     * <br>
     * <b>NOTE:</b> If you set custom memory cache then following configuration option will not be
     * considered:
     *
     * <ul>
     *   <li>{@link #memoryCacheSize(int)}
     * </ul>
     */
    public Builder memoryCache(MemoryCache memoryCache) {
      if (memoryCacheSize != 0) {
        L.w(WARNING_OVERLAP_MEMORY_CACHE);
      }

      this.memoryCache = memoryCache;
      return this;
    }
Example #17
0
  /**
   * Initializes ImageLoader instance with configuration.<br>
   * If configurations was set before ( {@link #isInited()} == true) then this method does nothing.
   * <br>
   * To force initialization with new configuration you should {@linkplain #destroy() destroy
   * ImageLoader} at first.
   *
   * @param configuration {@linkplain ImageLoaderConfiguration ImageLoader configuration}
   * @throws IllegalArgumentException if <b>configuration</b> parameter is null
   */
  public synchronized void init(ImageLoaderConfiguration configuration) {
    if (configuration == null) {
      throw new IllegalArgumentException(ERROR_INIT_CONFIG_WITH_NULL);
    }

    if (this.configuration == null) {
      if (configuration.writeLogs) {
        L.d(LOG_INIT_CONFIG);
      }

      engine = new ImageLoaderEngine(configuration);
      this.configuration = configuration;

    } else {
      L.w(WARNING_RE_INIT_CONFIG);
    }
  }
    /**
     * 设置本地文件缓存器中 缓存文件名生成器 Sets name generator for files cached in disk cache.<br>
     * Default value - {@link
     * com.nostra13.universalimageloader.core.DefaultConfigurationFactory#createFileNameGenerator()
     * DefaultConfigurationFactory.createFileNameGenerator()}
     */
    public Builder diskCacheFileNameGenerator(FileNameGenerator fileNameGenerator) {
      if (diskCache != null) {
        L.w(WARNING_OVERLAP_DISK_CACHE_NAME_GENERATOR);
      }

      this.diskCacheFileNameGenerator = fileNameGenerator;
      return this;
    }
    /**
     * 设置加载和显示图片任务的队列任务处理算法类型 Sets type of queue processing for tasks for loading and displaying
     * images.<br>
     * Default value - {@link QueueProcessingType#FIFO}
     */
    public Builder tasksProcessingOrder(QueueProcessingType tasksProcessingType) {
      if (taskExecutor != null || taskExecutorForCachedImages != null) {
        L.w(WARNING_OVERLAP_EXECUTOR);
      }

      this.tasksProcessingType = tasksProcessingType;
      return this;
    }
Example #20
0
  /**
   * {@linkplain #stop() Stops ImageLoader} and clears current configuration. <br>
   * You can {@linkplain #init(ImageLoaderConfiguration) init} ImageLoader with new configuration
   * after calling this method.
   */
  public void destroy() {
    if (configuration != null && configuration.writeLogs) {
      L.d(LOG_DESTROY);
    }

    stop();
    engine = null;
    configuration = null;
  }
 public tasksProcessingType threadPoolSize(int i)
 {
     if (taskExecutor != null || taskExecutorForCachedImages != null)
     {
         L.w("threadPoolSize(), threadPriority() and tasksProcessingOrder() calls can overlap taskExecutor() and taskExecutorForCachedImages() calls.", new Object[0]);
     }
     threadPoolSize = i;
     return this;
 }
 public taskExecutor taskExecutorForCachedImages(Executor executor)
 {
     if (threadPoolSize != 3 || threadPriority != 4 || tasksProcessingType != DEFAULT_TASK_PROCESSING_TYPE)
     {
         L.w("threadPoolSize(), threadPriority() and tasksProcessingOrder() calls can overlap taskExecutor() and taskExecutorForCachedImages() calls.", new Object[0]);
     }
     taskExecutorForCachedImages = executor;
     return this;
 }
 public downloader memoryCache(MemoryCache memorycache)
 {
     if (memoryCacheSize != 0)
     {
         L.w("memoryCache() and memoryCacheSize() calls overlap each other", new Object[0]);
     }
     memoryCache = memorycache;
     return this;
 }
 public diskCacheFileCount diskCacheFileNameGenerator(FileNameGenerator filenamegenerator)
 {
     if (diskCache != null)
     {
         L.w("diskCache() and diskCacheFileNameGenerator() calls overlap each other", new Object[0]);
     }
     diskCacheFileNameGenerator = filenamegenerator;
     return this;
 }
Example #25
0
 @Override
 public boolean remove(String imageUri) {
   try {
     return cache.remove(getKey(imageUri));
   } catch (IOException e) {
     L.e(e);
     return false;
   }
 }
Example #26
0
 @Override
 public void close() {
   try {
     cache.close();
   } catch (IOException e) {
     L.e(e);
   }
   cache = null;
 }
Example #27
0
 @Override
 public File get(String imageUri) {
   try {
     DiskLruCache.Snapshot snapshot = cache.get(getKey(imageUri));
     return snapshot == null ? null : snapshot.getFile(0);
   } catch (IOException e) {
     L.e(e);
     return null;
   }
 }
Example #28
0
 @Override
 public void clear() {
   try {
     cache.delete();
   } catch (IOException e) {
     L.e(e);
   } finally {
     initCache(cache.getDirectory(), reserveCacheDir, cache.getMaxSize(), cache.getMaxFileCount());
   }
 }
    /**
     * 设置图片缓存自定义执行者 Sets custom {@linkplain Executor executor} for tasks of displaying <b>cached on
     * disk</b> images (these tasks are executed quickly so UIL prefer to use separate executor for
     * them).<br>
     * <br>
     * If you set the same executor for {@linkplain #taskExecutor(Executor) general tasks} and tasks
     * about cached images (this method) then these tasks will be in the same thread pool. So
     * short-lived tasks can wait a long time for their turn.<br>
     * <br>
     * <b>NOTE:</b> If you set custom executor then following configuration options will not be
     * considered for this executor:
     *
     * <ul>
     *   <li>{@link #threadPoolSize(int)}
     *   <li>{@link #threadPriority(int)}
     *   <li>{@link #tasksProcessingOrder(QueueProcessingType)}
     * </ul>
     *
     * @see #taskExecutor(Executor)
     */
    public Builder taskExecutorForCachedImages(Executor executorForCachedImages) {
      if (threadPoolSize != DEFAULT_THREAD_POOL_SIZE
          || threadPriority != DEFAULT_THREAD_PRIORITY
          || tasksProcessingType != DEFAULT_TASK_PROCESSING_TYPE) {
        L.w(WARNING_OVERLAP_EXECUTOR);
      }

      this.taskExecutorForCachedImages = executorForCachedImages;
      return this;
    }
    /**
     * 设置本地文件缓存器中可缓存的文件大小 Sets maximum file count in disk cache directory.<br>
     * By default: disk cache is unlimited.<br>
     * <b>NOTE:</b> If you use this method then {@link
     * com.nostra13.universalimageloader.cache.disc.impl.ext.LruDiskCache LruDiskCache} will be used
     * as disk cache. You can use {@link #diskCache(DiskCache)} method for introduction your own
     * implementation of {@link DiskCache}
     */
    public Builder diskCacheFileCount(int maxFileCount) {
      if (maxFileCount <= 0)
        throw new IllegalArgumentException("maxFileCount must be a positive number");

      if (diskCache != null) {
        L.w(WARNING_OVERLAP_DISK_CACHE_PARAMS);
      }

      this.diskCacheFileCount = maxFileCount;
      return this;
    }