zoukankan      html  css  js  c++  java
  • Android-Universal-Image-Loader三大组件DisplayImageOptions、ImageLoader、ImageLoaderConfiguration详解

    一、介绍

     Android-Universal-Image-Loader是一个开源的UI组件程序,该项目的目的是提供一个可重复使用的仪器为异步图像加载,缓存和显示。所以,如果你的程序里需要这个功能的话,那么不妨试试它。因为已经封装好了一些类和方法。我们 可以直接拿来用了。而不用重复去写了。其实,写一个这方面的程序还是比较麻烦的,要考虑多线程缓存,内存溢出等很多方面。

    二、具体使用

    一个好的类库的重要特征就是可配置性强。我们先简单使用Android-Universal-Image-Loader,一般情况下使用默认配置就可以了。

    下面的实例利用Android-Universal-Image-Loader将网络图片加载到图片墙中。

    public class BaseActivity extends Activity {
        ImageLoader imageLoader;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
              // Create global configuration and initialize ImageLoader with this configuration
            ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
                .build();
            ImageLoader.getInstance().init(config);
            super.onCreate(savedInstanceState);
        }
    }
    public class MainActivity extends BaseActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
      
            ImageLoader imageLoader = ImageLoader.getInstance();
    
            GridView gridView = (GridView) this.findViewById(R.id.grdvImageWall);
            gridView.setAdapter(new PhotoWallAdapter(Constants.IMAGES));
        }
    
        static class ViewHolder {
            ImageView imageView;
            ProgressBar progressBar;
        }
    
        public class PhotoWallAdapter extends BaseAdapter {
            String[] imageUrls;
            ImageLoader imageLoad;
            DisplayImageOptions options;
            LinearLayout gridViewItem;
    
            public PhotoWallAdapter(String[] imageUrls) {
                assert imageUrls != null;
                this.imageUrls = imageUrls;
    
                options = new DisplayImageOptions.Builder()
                        .showImageOnLoading(R.drawable.ic_stub) // resource or
                                                                // drawable
                        .showImageForEmptyUri(R.drawable.ic_empty) // resource or
                                                                    // drawable
                        .showImageOnFail(R.drawable.ic_error) // resource or
                                                                // drawable
                        .resetViewBeforeLoading(false) // default
                        .delayBeforeLoading(1000).cacheInMemory(false) // default
                        .cacheOnDisk(false) // default
                        .considerExifParams(false) // default
                        .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default
                        .bitmapConfig(Bitmap.Config.ARGB_8888) // default
                        .displayer(new SimpleBitmapDisplayer()) // default
                        .handler(new Handler()) // default
                        .build();
                this.imageLoad = ImageLoader.getInstance();
    
            }
    
            @Override
            public int getCount() {
                return this.imageUrls.length;
            }
    
            @Override
            public Object getItem(int position) {
                if (position <= 0 || position >= this.imageUrls.length) {
                    throw new IllegalArgumentException(
                            "position<=0||position>=this.imageUrls.length");
                }
                return this.imageUrls[position];
            }
    
            @Override
            public long getItemId(int position) {
                return position;
            }
    
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                // 判断这个image是否已经在缓存当中,如果没有就下载
                final ViewHolder holder;
                if (convertView == null) {
                    holder = new ViewHolder();
                    gridViewItem = (LinearLayout) getLayoutInflater().inflate(
                            R.layout.image_wall_item, null);
                    holder.imageView = (ImageView) gridViewItem
                            .findViewById(R.id.item_image);
                    holder.progressBar = (ProgressBar) gridViewItem
                            .findViewById(R.id.item_process);
                    gridViewItem.setTag(holder);
                    convertView = gridViewItem;
                } else {
                    holder = (ViewHolder) gridViewItem.getTag();
                }
                this.imageLoad.displayImage(this.imageUrls[position],
                        holder.imageView, options,
                        new SimpleImageLoadingListener() {
    
                            @Override
                            public void onLoadingStarted(String imageUri, View view) {
                                holder.progressBar.setProgress(0);
                                holder.progressBar.setVisibility(View.VISIBLE);
                            }
    
                            @Override
                            public void onLoadingFailed(String imageUri, View view,
                                    FailReason failReason) {
                                holder.progressBar.setVisibility(View.GONE);
                            }
    
                            @Override
                            public void onLoadingComplete(String imageUri,
                                    View view, Bitmap loadedImage) {
                                holder.progressBar.setVisibility(View.GONE);
                            }
    
                        }, new ImageLoadingProgressListener() {
    
                            @Override
                            public void onProgressUpdate(String imageUri,
                                    View view, int current, int total) {
                                holder.progressBar.setProgress(Math.round(100.0f
                                        * current / total));
                            }
                        }); // 通过URL判断图片是否已经下载
                return convertView;
            }
    
        }
    }

    三者的关系

    ImageLoaderConfiguration是针对图片缓存的全局配置,主要有线程类、缓存大小、磁盘大小、图片下载与解析、日志方面的配置。

    ImageLoader是具体下载图片,缓存图片,显示图片的具体执行类,它有两个具体的方法displayImage(...)、loadImage(...),但是其实最终他们的实现都是displayImage(...)。

    DisplayImageOptions用于指导每一个Imageloader根据网络图片的状态(空白、下载错误、正在下载)显示对应的图片,是否将缓存加载到磁盘上,下载完后对图片进行怎么样的处理。

    从三者的协作关系上看,他们有点像厨房规定、厨师、客户个人口味之间的关系。ImageLoaderConfiguration就像是厨房里面的规定,每一个厨师要怎么着装,要怎么保持厨房的干净,这是针对每一个厨师都适用的规定,而且不允许个性化改变。ImageLoader就像是具体做菜的厨师,负责具体菜谱的制作。DisplayImageOptions就像每个客户的偏好,根据客户是重口味还是清淡,每一个imageLoader根据DisplayImageOptions的要求具体执行。

    ImageLoaderConfiguration

    在上面的示例代码中,我们使用ImageLoaderConfiguration的默认配置,下面给出ImageLoaderConfiguration比较详尽的配置,从下面的配置中,可以看出ImageLoaderConfiguration的配置主要是全局性的配置,主要有线程类、缓存大小、磁盘大小、图片下载与解析、日志方面的配置。

    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
            .memoryCacheExtraOptions(480, 800) // default = device screen dimensions
            .diskCacheExtraOptions(480, 800, null)
            .taskExecutor(...)
            .taskExecutorForCachedImages(...)
            .threadPoolSize(3) // default
            .threadPriority(Thread.NORM_PRIORITY - 1) // default
            .tasksProcessingOrder(QueueProcessingType.FIFO) // default
            .denyCacheImageMultipleSizesInMemory()
            .memoryCache(new LruMemoryCache(2 * 1024 * 1024))
            .memoryCacheSize(2 * 1024 * 1024)
            .memoryCacheSizePercentage(13) // default
            .diskCache(new UnlimitedDiscCache(cacheDir)) // default
            .diskCacheSize(50 * 1024 * 1024)
            .diskCacheFileCount(100)
            .diskCacheFileNameGenerator(new HashCodeFileNameGenerator()) // default
            .imageDownloader(new BaseImageDownloader(context)) // default
            .imageDecoder(new BaseImageDecoder()) // default
            .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default
            .writeDebugLogs()
            .build();

    ImageLoaderConfiguration的主要职责就是记录相关的配置,它的内部其实就是一些字段的集合(如下面的源代码)。它有一个builder的内部类,这个类中的字段跟ImageLoaderConfiguration中的字段完全一致,它有一些默认值,通过修改builder可以配置ImageLoaderConfiguration。

    /*******************************************************************************
     * Copyright 2011-2013 Sergey Tarasevich
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     * http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     *******************************************************************************/
    package com.nostra13.universalimageloader.core;
    
    import android.content.Context;
    import android.content.res.Resources;
    import android.util.DisplayMetrics;
    import com.nostra13.universalimageloader.cache.disc.DiskCache;
    import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator;
    import com.nostra13.universalimageloader.cache.memory.MemoryCache;
    import com.nostra13.universalimageloader.cache.memory.impl.FuzzyKeyMemoryCache;
    import com.nostra13.universalimageloader.core.assist.FlushedInputStream;
    import com.nostra13.universalimageloader.core.assist.ImageSize;
    import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
    import com.nostra13.universalimageloader.core.decode.ImageDecoder;
    import com.nostra13.universalimageloader.core.download.ImageDownloader;
    import com.nostra13.universalimageloader.core.process.BitmapProcessor;
    import com.nostra13.universalimageloader.utils.L;
    import com.nostra13.universalimageloader.utils.MemoryCacheUtils;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.concurrent.Executor;
    
    /**
     * Presents configuration for {@link ImageLoader}
     *
     * @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
     * @see ImageLoader
     * @see MemoryCache
     * @see DiskCache
     * @see DisplayImageOptions
     * @see ImageDownloader
     * @see FileNameGenerator
     * @since 1.0.0
     */
    public final class ImageLoaderConfiguration {
    
        final Resources resources;
    
        final int maxImageWidthForMemoryCache;
        final int maxImageHeightForMemoryCache;
        final int maxImageWidthForDiskCache;
        final int maxImageHeightForDiskCache;
        final BitmapProcessor processorForDiskCache;
    
        final Executor taskExecutor;
        final Executor taskExecutorForCachedImages;
        final boolean customExecutor;
        final boolean customExecutorForCachedImages;
    
        final int threadPoolSize;
        final int threadPriority;
        final QueueProcessingType tasksProcessingType;
    
        final MemoryCache memoryCache;
        final DiskCache diskCache;
        final ImageDownloader downloader;
        final ImageDecoder decoder;
        final DisplayImageOptions defaultDisplayImageOptions;
    
        final ImageDownloader networkDeniedDownloader;
        final ImageDownloader slowNetworkDownloader;
    
        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);
        }
    
        /**
         * Creates default configuration for {@link ImageLoader} <br />
         * <b>Default values:</b>
         * <ul>
         * <li>maxImageWidthForMemoryCache = device's screen width</li>
         * <li>maxImageHeightForMemoryCache = device's screen height</li>
         * <li>maxImageWidthForDikcCache = unlimited</li>
         * <li>maxImageHeightForDiskCache = unlimited</li>
         * <li>threadPoolSize = {@link Builder#DEFAULT_THREAD_POOL_SIZE this}</li>
         * <li>threadPriority = {@link Builder#DEFAULT_THREAD_PRIORITY this}</li>
         * <li>allow to cache different sizes of image in memory</li>
         * <li>memoryCache = {@link DefaultConfigurationFactory#createMemoryCache(int)}</li>
         * <li>diskCache = {@link com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache}</li>
         * <li>imageDownloader = {@link DefaultConfigurationFactory#createImageDownloader(Context)}</li>
         * <li>imageDecoder = {@link DefaultConfigurationFactory#createImageDecoder(boolean)}</li>
         * <li>diskCacheFileNameGenerator = {@link DefaultConfigurationFactory#createFileNameGenerator()}</li>
         * <li>defaultDisplayImageOptions = {@link DisplayImageOptions#createSimple() Simple options}</li>
         * <li>tasksProcessingOrder = {@link QueueProcessingType#FIFO}</li>
         * <li>detailed logging disabled</li>
         * </ul>
         */
        public static ImageLoaderConfiguration createDefault(Context context) {
            return new Builder(context).build();
        }
    
        ImageSize getMaxImageSize() {
            DisplayMetrics displayMetrics = resources.getDisplayMetrics();
    
            int width = maxImageWidthForMemoryCache;
            if (width <= 0) {
                width = displayMetrics.widthPixels;
            }
            int height = maxImageHeightForMemoryCache;
            if (height <= 0) {
                height = displayMetrics.heightPixels;
            }
            return new ImageSize(width, height);
        }
    
        /**
         * Builder for {@link ImageLoaderConfiguration}
         *
         * @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
         */
        public static class Builder {
    
            private static final String WARNING_OVERLAP_DISK_CACHE_PARAMS = "diskCache(), diskCacheSize() and diskCacheFileCount calls overlap each other";
            private static final String WARNING_OVERLAP_DISK_CACHE_NAME_GENERATOR = "diskCache() and diskCacheFileNameGenerator() calls overlap each other";
            private static final String WARNING_OVERLAP_MEMORY_CACHE = "memoryCache() and memoryCacheSize() calls overlap each other";
            private static final String WARNING_OVERLAP_EXECUTOR = "threadPoolSize(), threadPriority() and tasksProcessingOrder() calls "
                    + "can overlap taskExecutor() and taskExecutorForCachedImages() calls.";
    
            /** {@value} */
            public static final int DEFAULT_THREAD_POOL_SIZE = 3;
            /** {@value} */
            public static final int DEFAULT_THREAD_PRIORITY = Thread.NORM_PRIORITY - 1;
            /** {@value} */
            public static final QueueProcessingType DEFAULT_TASK_PROCESSING_TYPE = QueueProcessingType.FIFO;
    
            private Context context;
    
            private int maxImageWidthForMemoryCache = 0;
            private int maxImageHeightForMemoryCache = 0;
            private int maxImageWidthForDiskCache = 0;
            private int maxImageHeightForDiskCache = 0;
            private BitmapProcessor processorForDiskCache = null;
    
            private Executor taskExecutor = null;
            private Executor taskExecutorForCachedImages = null;
            private boolean customExecutor = false;
            private boolean customExecutorForCachedImages = false;
    
            private int threadPoolSize = DEFAULT_THREAD_POOL_SIZE;
            private int threadPriority = DEFAULT_THREAD_PRIORITY;
            private boolean denyCacheImageMultipleSizesInMemory = false;
            private QueueProcessingType tasksProcessingType = DEFAULT_TASK_PROCESSING_TYPE;
    
            private int memoryCacheSize = 0;
            private long diskCacheSize = 0;
            private int diskCacheFileCount = 0;
    
            private MemoryCache memoryCache = null;
            private DiskCache diskCache = null;
            private FileNameGenerator diskCacheFileNameGenerator = null;
            private ImageDownloader downloader = null;
            private ImageDecoder decoder;
            private DisplayImageOptions defaultDisplayImageOptions = null;
    
            private boolean writeLogs = false;
    
            public Builder(Context context) {
                this.context = context.getApplicationContext();
            }
    
            /**
             * Sets options for memory cache
             *
             * @param maxImageWidthForMemoryCache  Maximum image width which will be used for memory saving during decoding
             *                                     an image to {@link android.graphics.Bitmap Bitmap}. <b>Default value - device's screen width</b>
             * @param maxImageHeightForMemoryCache Maximum image height which will be used for memory saving during decoding
             *                                     an image to {@link android.graphics.Bitmap Bitmap}. <b>Default value</b> - device's screen height
             */
            public Builder memoryCacheExtraOptions(int maxImageWidthForMemoryCache, int maxImageHeightForMemoryCache) {
                this.maxImageWidthForMemoryCache = maxImageWidthForMemoryCache;
                this.maxImageHeightForMemoryCache = maxImageHeightForMemoryCache;
                return this;
            }
    
            /**
             * @deprecated Use
             * {@link #diskCacheExtraOptions(int, int, com.nostra13.universalimageloader.core.process.BitmapProcessor)}
             * instead
             */
            @Deprecated
            public Builder discCacheExtraOptions(int maxImageWidthForDiskCache, int maxImageHeightForDiskCache,
                    BitmapProcessor processorForDiskCache) {
                return diskCacheExtraOptions(maxImageWidthForDiskCache, maxImageHeightForDiskCache, processorForDiskCache);
            }
    
            /**
             * Sets options for resizing/compressing of downloaded images before saving to disk cache.<br />
             * <b>NOTE: Use this option only when you have appropriate needs. It can make ImageLoader slower.</b>
             *
             * @param maxImageWidthForDiskCache  Maximum width of downloaded images for saving at disk cache
             * @param maxImageHeightForDiskCache Maximum height of downloaded images for saving at disk cache
             * @param processorForDiskCache      null-ok; {@linkplain BitmapProcessor Bitmap processor} which process images before saving them in disc cache
             */
            public Builder diskCacheExtraOptions(int maxImageWidthForDiskCache, int maxImageHeightForDiskCache,
                    BitmapProcessor processorForDiskCache) {
                this.maxImageWidthForDiskCache = maxImageWidthForDiskCache;
                this.maxImageHeightForDiskCache = maxImageHeightForDiskCache;
                this.processorForDiskCache = processorForDiskCache;
                return this;
            }
    
            /**
             * Sets custom {@linkplain Executor executor} for tasks of loading and displaying images.<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>
             * <li>{@link #threadPriority(int)}</li>
             * <li>{@link #tasksProcessingOrder(QueueProcessingType)}</li>
             * </ul>
             *
             * @see #taskExecutorForCachedImages(Executor)
             */
            public Builder taskExecutor(Executor executor) {
                if (threadPoolSize != DEFAULT_THREAD_POOL_SIZE || threadPriority != DEFAULT_THREAD_PRIORITY || tasksProcessingType != DEFAULT_TASK_PROCESSING_TYPE) {
                    L.w(WARNING_OVERLAP_EXECUTOR);
                }
    
                this.taskExecutor = executor;
                return this;
            }
    
            /**
             * 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>
             * <li>{@link #threadPriority(int)}</li>
             * <li>{@link #tasksProcessingOrder(QueueProcessingType)}</li>
             * </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 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 the priority for image loading threads. Should be <b>NOT</b> greater than {@link Thread#MAX_PRIORITY} or
             * less than {@link Thread#MIN_PRIORITY}<br />
             * Default value - {@link #DEFAULT_THREAD_PRIORITY this}
             */
            public Builder threadPriority(int threadPriority) {
                if (taskExecutor != null || taskExecutorForCachedImages != null) {
                    L.w(WARNING_OVERLAP_EXECUTOR);
                }
    
                if (threadPriority < Thread.MIN_PRIORITY) {
                    this.threadPriority = Thread.MIN_PRIORITY;
                } else {
                    if (threadPriority > Thread.MAX_PRIORITY) {
                        this.threadPriority = Thread.MAX_PRIORITY;
                    } else {
                        this.threadPriority = threadPriority;
                    }
                }
                return this;
            }
    
            /**
             * When you display an image in a small {@link android.widget.ImageView ImageView} and later you try to display
             * this image (from identical URI) in a larger {@link android.widget.ImageView ImageView} so decoded image of
             * bigger size will be cached in memory as a previous decoded image of smaller size.<br />
             * So <b>the default behavior is to allow to cache multiple sizes of one image in memory</b>. You can
             * <b>deny</b> it by calling <b>this</b> method: so when some image will be cached in memory then previous
             * cached size of this image (if it exists) will be removed from memory cache before.
             */
            public Builder denyCacheImageMultipleSizesInMemory() {
                this.denyCacheImageMultipleSizesInMemory = true;
                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;
            }
    
            /**
             * Sets maximum memory cache size for {@link android.graphics.Bitmap bitmaps} (in bytes).<br />
             * Default value - 1/8 of available app memory.<br />
             * <b>NOTE:</b> If you use this method then
             * {@link com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache LruMemoryCache} will be used as
             * memory cache. You can use {@link #memoryCache(MemoryCache)} method to set your own implementation of
             * {@link MemoryCache}.
             */
            public Builder memoryCacheSize(int memoryCacheSize) {
                if (memoryCacheSize <= 0) throw new IllegalArgumentException("memoryCacheSize must be a positive number");
    
                if (memoryCache != null) {
                    L.w(WARNING_OVERLAP_MEMORY_CACHE);
                }
    
                this.memoryCacheSize = memoryCacheSize;
                return this;
            }
    
            /**
             * Sets maximum memory cache size (in percent of available app memory) for {@link android.graphics.Bitmap
             * bitmaps}.<br />
             * Default value - 1/8 of available app memory.<br />
             * <b>NOTE:</b> If you use this method then
             * {@link com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache LruMemoryCache} will be used as
             * memory cache. You can use {@link #memoryCache(MemoryCache)} method to set your own implementation of
             * {@link MemoryCache}.
             */
            public Builder memoryCacheSizePercentage(int availableMemoryPercent) {
                if (availableMemoryPercent <= 0 || availableMemoryPercent >= 100) {
                    throw new IllegalArgumentException("availableMemoryPercent must be in range (0 < % < 100)");
                }
    
                if (memoryCache != null) {
                    L.w(WARNING_OVERLAP_MEMORY_CACHE);
                }
    
                long availableMemory = Runtime.getRuntime().maxMemory();
                memoryCacheSize = (int) (availableMemory * (availableMemoryPercent / 100f));
                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)}</li>
             * </ul>
             */
            public Builder memoryCache(MemoryCache memoryCache) {
                if (memoryCacheSize != 0) {
                    L.w(WARNING_OVERLAP_MEMORY_CACHE);
                }
    
                this.memoryCache = memoryCache;
                return this;
            }
    
            /** @deprecated Use {@link #diskCacheSize(int)} instead */
            @Deprecated
            public Builder discCacheSize(int maxCacheSize) {
                return diskCacheSize(maxCacheSize);
            }
    
            /**
             * Sets maximum disk cache size for images (in bytes).<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.LruDiscCache LruDiscCache}
             * will be used as disk cache. You can use {@link #diskCache(DiskCache)} method for introduction your own
             * implementation of {@link DiskCache}
             */
            public Builder diskCacheSize(int maxCacheSize) {
                if (maxCacheSize <= 0) throw new IllegalArgumentException("maxCacheSize must be a positive number");
    
                if (diskCache != null) {
                    L.w(WARNING_OVERLAP_DISK_CACHE_PARAMS);
                }
    
                this.diskCacheSize = maxCacheSize;
                return this;
            }
    
            /** @deprecated Use {@link #diskCacheFileCount(int)} instead */
            @Deprecated
            public Builder discCacheFileCount(int maxFileCount) {
                return diskCacheFileCount(maxFileCount);
            }
    
            /**
             * 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.LruDiscCache LruDiscCache}
             * 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;
            }
    
            /** @deprecated Use {@link #diskCacheFileNameGenerator(com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator)} */
            @Deprecated
            public Builder discCacheFileNameGenerator(FileNameGenerator fileNameGenerator) {
                return diskCacheFileNameGenerator(fileNameGenerator);
            }
    
            /**
             * 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;
            }
    
            /** @deprecated Use {@link #diskCache(com.nostra13.universalimageloader.cache.disc.DiskCache)} */
            @Deprecated
            public Builder discCache(DiskCache diskCache) {
                return diskCache(diskCache);
            }
    
            /**
             * Sets disk cache for images.<br />
             * Default value - {@link com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache
             * BaseDiscCache}. 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>
             * <li>{@link #diskCacheFileCount(int)}</li>
             * <li>{@link #diskCacheFileNameGenerator(FileNameGenerator)}</li>
             * </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;
            }
    
            /**
             * Sets utility which will be responsible for downloading of image.<br />
             * Default value -
             * {@link com.nostra13.universalimageloader.core.DefaultConfigurationFactory#createImageDownloader(Context)
             * DefaultConfigurationFactory.createImageDownloader()}
             */
            public Builder imageDownloader(ImageDownloader imageDownloader) {
                this.downloader = imageDownloader;
                return this;
            }
    
            /**
             * Sets utility which will be responsible for decoding of image stream.<br />
             * Default value -
             * {@link com.nostra13.universalimageloader.core.DefaultConfigurationFactory#createImageDecoder(boolean)
             * DefaultConfigurationFactory.createImageDecoder()}
             */
            public Builder imageDecoder(ImageDecoder imageDecoder) {
                this.decoder = imageDecoder;
                return this;
            }
    
            /**
             * Sets default {@linkplain DisplayImageOptions display image options} for image displaying. These options will
             * be used for every {@linkplain ImageLoader#displayImage(String, android.widget.ImageView) image display call}
             * without passing custom {@linkplain DisplayImageOptions options}<br />
             * Default value - {@link DisplayImageOptions#createSimple() Simple options}
             */
            public Builder defaultDisplayImageOptions(DisplayImageOptions defaultDisplayImageOptions) {
                this.defaultDisplayImageOptions = defaultDisplayImageOptions;
                return this;
            }
    
            /**
             * Enables detail logging of {@link ImageLoader} work. To prevent detail logs don't call this method.
             * Consider {@link com.nostra13.universalimageloader.utils.L#disableLogging()} to disable
             * ImageLoader logging completely (even error logs)
             */
            public Builder writeDebugLogs() {
                this.writeLogs = true;
                return this;
            }
    
            /** Builds configured {@link ImageLoaderConfiguration} object */
            public ImageLoaderConfiguration build() {
                initEmptyFieldsWithDefaultValues();
                return new ImageLoaderConfiguration(this);
            }
    
            private void initEmptyFieldsWithDefaultValues() {
                if (taskExecutor == null) {
                    taskExecutor = DefaultConfigurationFactory
                            .createExecutor(threadPoolSize, threadPriority, tasksProcessingType);
                } else {
                    customExecutor = true;
                }
                if (taskExecutorForCachedImages == null) {
                    taskExecutorForCachedImages = DefaultConfigurationFactory
                            .createExecutor(threadPoolSize, threadPriority, tasksProcessingType);
                } else {
                    customExecutorForCachedImages = true;
                }
                if (diskCache == null) {
                    if (diskCacheFileNameGenerator == null) {
                        diskCacheFileNameGenerator = DefaultConfigurationFactory.createFileNameGenerator();
                    }
                    diskCache = DefaultConfigurationFactory
                            .createDiskCache(context, diskCacheFileNameGenerator, diskCacheSize, diskCacheFileCount);
                }
                if (memoryCache == null) {
                    memoryCache = DefaultConfigurationFactory.createMemoryCache(memoryCacheSize);
                }
                if (denyCacheImageMultipleSizesInMemory) {
                    memoryCache = new FuzzyKeyMemoryCache(memoryCache, MemoryCacheUtils.createFuzzyKeyComparator());
                }
                if (downloader == null) {
                    downloader = DefaultConfigurationFactory.createImageDownloader(context);
                }
                if (decoder == null) {
                    decoder = DefaultConfigurationFactory.createImageDecoder(writeLogs);
                }
                if (defaultDisplayImageOptions == null) {
                    defaultDisplayImageOptions = DisplayImageOptions.createSimple();
                }
            }
        }
    
        /**
         * Decorator. Prevents downloads from network (throws {@link IllegalStateException exception}).<br />
         * In most cases this downloader shouldn't be used directly.
         *
         * @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
         * @since 1.8.0
         */
        private static class NetworkDeniedImageDownloader implements ImageDownloader {
    
            private final ImageDownloader wrappedDownloader;
    
            public NetworkDeniedImageDownloader(ImageDownloader wrappedDownloader) {
                this.wrappedDownloader = wrappedDownloader;
            }
    
            @Override
            public InputStream getStream(String imageUri, Object extra) throws IOException {
                switch (Scheme.ofUri(imageUri)) {
                    case HTTP:
                    case HTTPS:
                        throw new IllegalStateException();
                    default:
                        return wrappedDownloader.getStream(imageUri, extra);
                }
            }
        }
    
        /**
         * Decorator. Handles <a href="http://code.google.com/p/android/issues/detail?id=6066">this problem</a> on slow networks
         * using {@link com.nostra13.universalimageloader.core.assist.FlushedInputStream}.
         *
         * @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
         * @since 1.8.1
         */
        private static class SlowNetworkImageDownloader implements ImageDownloader {
    
            private final ImageDownloader wrappedDownloader;
    
            public SlowNetworkImageDownloader(ImageDownloader wrappedDownloader) {
                this.wrappedDownloader = wrappedDownloader;
            }
    
            @Override
            public InputStream getStream(String imageUri, Object extra) throws IOException {
                InputStream imageStream = wrappedDownloader.getStream(imageUri, extra);
                switch (Scheme.ofUri(imageUri)) {
                    case HTTP:
                    case HTTPS:
                        return new FlushedInputStream(imageStream);
                    default:
                        return imageStream;
                }
            }
        }
    }

     Display Options

    每一个ImageLoader.displayImage(...)都可以使用Display Options

    DisplayImageOptions options = new DisplayImageOptions.Builder()
            .showImageOnLoading(R.drawable.ic_stub) // resource or drawable
            .showImageForEmptyUri(R.drawable.ic_empty) // resource or drawable
            .showImageOnFail(R.drawable.ic_error) // resource or drawable
            .resetViewBeforeLoading(false)  // default
            .delayBeforeLoading(1000)
            .cacheInMemory(false) // default
            .cacheOnDisk(false) // default
            .preProcessor(...)
            .postProcessor(...)
            .extraForDownloader(...)
            .considerExifParams(false) // default
            .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default
            .bitmapConfig(Bitmap.Config.ARGB_8888) // default
            .decodingOptions(...)
            .displayer(new SimpleBitmapDisplayer()) // default
            .handler(new Handler()) // default
            .build();

     Display Options的主要职责就是记录相关的配置,它的内部其实就是一些字段的集合(如下面的源代码)。它有一个builder的内部类,这个类中的字段跟DisplayOption中的字段完全一致,它有一些默认值,通过修改builder可以配置DisplayOptions。

    public final class DisplayImageOptions {
    
        private final int imageResOnLoading;
        private final int imageResForEmptyUri;
        private final int imageResOnFail;
        private final Drawable imageOnLoading;
        private final Drawable imageForEmptyUri;
        private final Drawable imageOnFail;
        private final boolean resetViewBeforeLoading;
        private final boolean cacheInMemory;
        private final boolean cacheOnDisk;
        private final ImageScaleType imageScaleType;
        private final Options decodingOptions;
        private final int delayBeforeLoading;
        private final boolean considerExifParams;
        private final Object extraForDownloader;
        private final BitmapProcessor preProcessor;
        private final BitmapProcessor postProcessor;
        private final BitmapDisplayer displayer;
        private final Handler handler;
        private final boolean isSyncLoading;
    
        private DisplayImageOptions(Builder builder) {
            imageResOnLoading = builder.imageResOnLoading;
            imageResForEmptyUri = builder.imageResForEmptyUri;
            imageResOnFail = builder.imageResOnFail;
            imageOnLoading = builder.imageOnLoading;
            imageForEmptyUri = builder.imageForEmptyUri;
            imageOnFail = builder.imageOnFail;
            resetViewBeforeLoading = builder.resetViewBeforeLoading;
            cacheInMemory = builder.cacheInMemory;
            cacheOnDisk = builder.cacheOnDisk;
            imageScaleType = builder.imageScaleType;
            decodingOptions = builder.decodingOptions;
            delayBeforeLoading = builder.delayBeforeLoading;
            considerExifParams = builder.considerExifParams;
            extraForDownloader = builder.extraForDownloader;
            preProcessor = builder.preProcessor;
            postProcessor = builder.postProcessor;
            displayer = builder.displayer;
            handler = builder.handler;
            isSyncLoading = builder.isSyncLoading;
        }
    
        public boolean shouldShowImageOnLoading() {
            return imageOnLoading != null || imageResOnLoading != 0;
        }
    
        public boolean shouldShowImageForEmptyUri() {
            return imageForEmptyUri != null || imageResForEmptyUri != 0;
        }
    
        public boolean shouldShowImageOnFail() {
            return imageOnFail != null || imageResOnFail != 0;
        }
    
        public boolean shouldPreProcess() {
            return preProcessor != null;
        }
    
        public boolean shouldPostProcess() {
            return postProcessor != null;
        }
    
        public boolean shouldDelayBeforeLoading() {
            return delayBeforeLoading > 0;
        }
    
        public Drawable getImageOnLoading(Resources res) {
            return imageResOnLoading != 0 ? res.getDrawable(imageResOnLoading) : imageOnLoading;
        }
    
        public Drawable getImageForEmptyUri(Resources res) {
            return imageResForEmptyUri != 0 ? res.getDrawable(imageResForEmptyUri) : imageForEmptyUri;
        }
    
        public Drawable getImageOnFail(Resources res) {
            return imageResOnFail != 0 ? res.getDrawable(imageResOnFail) : imageOnFail;
        }
    
        public boolean isResetViewBeforeLoading() {
            return resetViewBeforeLoading;
        }
    
        public boolean isCacheInMemory() {
            return cacheInMemory;
        }
    
        public boolean isCacheOnDisk() {
            return cacheOnDisk;
        }
    
        public ImageScaleType getImageScaleType() {
            return imageScaleType;
        }
    
        public Options getDecodingOptions() {
            return decodingOptions;
        }
    
        public int getDelayBeforeLoading() {
            return delayBeforeLoading;
        }
    
        public boolean isConsiderExifParams() {
            return considerExifParams;
        }
    
        public Object getExtraForDownloader() {
            return extraForDownloader;
        }
    
        public BitmapProcessor getPreProcessor() {
            return preProcessor;
        }
    
        public BitmapProcessor getPostProcessor() {
            return postProcessor;
        }
    
        public BitmapDisplayer getDisplayer() {
            return displayer;
        }
    
        public Handler getHandler() {
            return handler;
        }
    
        boolean isSyncLoading() {
            return isSyncLoading;
        }
    
        /**
         * Builder for {@link DisplayImageOptions}
         *
         * @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
         */
        public static class Builder {
            private int imageResOnLoading = 0;
            private int imageResForEmptyUri = 0;
            private int imageResOnFail = 0;
            private Drawable imageOnLoading = null;
            private Drawable imageForEmptyUri = null;
            private Drawable imageOnFail = null;
            private boolean resetViewBeforeLoading = false;
            private boolean cacheInMemory = false;
            private boolean cacheOnDisk = false;
            private ImageScaleType imageScaleType = ImageScaleType.IN_SAMPLE_POWER_OF_2;
            private Options decodingOptions = new Options();
            private int delayBeforeLoading = 0;
            private boolean considerExifParams = false;
            private Object extraForDownloader = null;
            private BitmapProcessor preProcessor = null;
            private BitmapProcessor postProcessor = null;
            private BitmapDisplayer displayer = DefaultConfigurationFactory.createBitmapDisplayer();
            private Handler handler = null;
            private boolean isSyncLoading = false;
    
            public Builder() {
                decodingOptions.inPurgeable = true;
                decodingOptions.inInputShareable = true;
            }
    
            /**
             * Stub image will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware
             * image aware view} during image loading
             *
             * @param imageRes Stub image resource
             * @deprecated Use {@link #showImageOnLoading(int)} instead
             */
            @Deprecated
            public Builder showStubImage(int imageRes) {
                imageResOnLoading = imageRes;
                return this;
            }
    
            /**
             * Incoming image will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware
             * image aware view} during image loading
             *
             * @param imageRes Image resource
             */
            public Builder showImageOnLoading(int imageRes) {
                imageResOnLoading = imageRes;
                return this;
            }
    
            /**
             * Incoming drawable will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware
             * image aware view} during image loading.
             * This option will be ignored if {@link DisplayImageOptions.Builder#showImageOnLoading(int)} is set.
             */
            public Builder showImageOnLoading(Drawable drawable) {
                imageOnLoading = drawable;
                return this;
            }
    
            /**
             * Incoming image will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware
             * image aware view} if empty URI (null or empty
             * string) will be passed to <b>ImageLoader.displayImage(...)</b> method.
             *
             * @param imageRes Image resource
             */
            public Builder showImageForEmptyUri(int imageRes) {
                imageResForEmptyUri = imageRes;
                return this;
            }
    
            /**
             * Incoming drawable will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware
             * image aware view} if empty URI (null or empty
             * string) will be passed to <b>ImageLoader.displayImage(...)</b> method.
             * This option will be ignored if {@link DisplayImageOptions.Builder#showImageForEmptyUri(int)} is set.
             */
            public Builder showImageForEmptyUri(Drawable drawable) {
                imageForEmptyUri = drawable;
                return this;
            }
    
            /**
             * Incoming image will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware
             * image aware view} if some error occurs during
             * requested image loading/decoding.
             *
             * @param imageRes Image resource
             */
            public Builder showImageOnFail(int imageRes) {
                imageResOnFail = imageRes;
                return this;
            }
    
            /**
             * Incoming drawable will be displayed in {@link com.nostra13.universalimageloader.core.imageaware.ImageAware
             * image aware view} if some error occurs during
             * requested image loading/decoding.
             * This option will be ignored if {@link DisplayImageOptions.Builder#showImageOnFail(int)} is set.
             */
            public Builder showImageOnFail(Drawable drawable) {
                imageOnFail = drawable;
                return this;
            }
    
            /**
             * {@link com.nostra13.universalimageloader.core.imageaware.ImageAware
             * image aware view} will be reset (set <b>null</b>) before image loading start
             *
             * @deprecated Use {@link #resetViewBeforeLoading(boolean) resetViewBeforeLoading(true)} instead
             */
            public Builder resetViewBeforeLoading() {
                resetViewBeforeLoading = true;
                return this;
            }
    
            /**
             * Sets whether {@link com.nostra13.universalimageloader.core.imageaware.ImageAware
             * image aware view} will be reset (set <b>null</b>) before image loading start
             */
            public Builder resetViewBeforeLoading(boolean resetViewBeforeLoading) {
                this.resetViewBeforeLoading = resetViewBeforeLoading;
                return this;
            }
    
            /**
             * Loaded image will be cached in memory
             *
             * @deprecated Use {@link #cacheInMemory(boolean) cacheInMemory(true)} instead
             */
            @Deprecated
            public Builder cacheInMemory() {
                cacheInMemory = true;
                return this;
            }
    
            /** Sets whether loaded image will be cached in memory */
            public Builder cacheInMemory(boolean cacheInMemory) {
                this.cacheInMemory = cacheInMemory;
                return this;
            }
    
            /**
             * Loaded image will be cached on disk
             *
             * @deprecated Use {@link #cacheOnDisk(boolean) cacheOnDisk(true)} instead
             */
            @Deprecated
            public Builder cacheOnDisc() {
                return cacheOnDisk(true);
            }
    
            /**
             * Sets whether loaded image will be cached on disk
             *
             * @deprecated Use {@link #cacheOnDisk(boolean)} instead
             */
            @Deprecated
            public Builder cacheOnDisc(boolean cacheOnDisk) {
                return cacheOnDisk(cacheOnDisk);
            }
    
            /** Sets whether loaded image will be cached on disk */
            public Builder cacheOnDisk(boolean cacheOnDisk) {
                this.cacheOnDisk = cacheOnDisk;
                return this;
            }
    
            /**
             * Sets {@linkplain ImageScaleType scale type} for decoding image. This parameter is used while define scale
             * size for decoding image to Bitmap. Default value - {@link ImageScaleType#IN_SAMPLE_POWER_OF_2}
             */
            public Builder imageScaleType(ImageScaleType imageScaleType) {
                this.imageScaleType = imageScaleType;
                return this;
            }
    
            /** Sets {@link Bitmap.Config bitmap config} for image decoding. Default value - {@link Bitmap.Config#ARGB_8888} */
            public Builder bitmapConfig(Bitmap.Config bitmapConfig) {
                if (bitmapConfig == null) throw new IllegalArgumentException("bitmapConfig can't be null");
                decodingOptions.inPreferredConfig = bitmapConfig;
                return this;
            }
    
            /**
             * Sets options for image decoding.<br />
             * <b>NOTE:</b> {@link Options#inSampleSize} of incoming options will <b>NOT</b> be considered. Library
             * calculate the most appropriate sample size itself according yo {@link #imageScaleType(ImageScaleType)}
             * options.<br />
             * <b>NOTE:</b> This option overlaps {@link #bitmapConfig(android.graphics.Bitmap.Config) bitmapConfig()}
             * option.
             */
            public Builder decodingOptions(Options decodingOptions) {
                if (decodingOptions == null) throw new IllegalArgumentException("decodingOptions can't be null");
                this.decodingOptions = decodingOptions;
                return this;
            }
    
            /** Sets delay time before starting loading task. Default - no delay. */
            public Builder delayBeforeLoading(int delayInMillis) {
                this.delayBeforeLoading = delayInMillis;
                return this;
            }
    
            /** Sets auxiliary object which will be passed to {@link ImageDownloader#getStream(String, Object)} */
            public Builder extraForDownloader(Object extra) {
                this.extraForDownloader = extra;
                return this;
            }
    
            /** Sets whether ImageLoader will consider EXIF parameters of JPEG image (rotate, flip) */
            public Builder considerExifParams(boolean considerExifParams) {
                this.considerExifParams = considerExifParams;
                return this;
            }
    
            /**
             * Sets bitmap processor which will be process bitmaps before they will be cached in memory. So memory cache
             * will contain bitmap processed by incoming preProcessor.<br />
             * Image will be pre-processed even if caching in memory is disabled.
             */
            public Builder preProcessor(BitmapProcessor preProcessor) {
                this.preProcessor = preProcessor;
                return this;
            }
    
            /**
             * Sets bitmap processor which will be process bitmaps before they will be displayed in
             * {@link com.nostra13.universalimageloader.core.imageaware.ImageAware image aware view} but
             * after they'll have been saved in memory cache.
             */
            public Builder postProcessor(BitmapProcessor postProcessor) {
                this.postProcessor = postProcessor;
                return this;
            }
    
            /**
             * Sets custom {@link BitmapDisplayer displayer} for image loading task. Default value -
             * {@link DefaultConfigurationFactory#createBitmapDisplayer()}
             */
            public Builder displayer(BitmapDisplayer displayer) {
                if (displayer == null) throw new IllegalArgumentException("displayer can't be null");
                this.displayer = displayer;
                return this;
            }
    
            Builder syncLoading(boolean isSyncLoading) {
                this.isSyncLoading = isSyncLoading;
                return this;
            }
    
            /**
             * Sets custom {@linkplain Handler handler} for displaying images and firing {@linkplain ImageLoadingListener
             * listener} events.
             */
            public Builder handler(Handler handler) {
                this.handler = handler;
                return this;
            }
    
            /** Sets all options equal to incoming options */
            public Builder cloneFrom(DisplayImageOptions options) {
                imageResOnLoading = options.imageResOnLoading;
                imageResForEmptyUri = options.imageResForEmptyUri;
                imageResOnFail = options.imageResOnFail;
                imageOnLoading = options.imageOnLoading;
                imageForEmptyUri = options.imageForEmptyUri;
                imageOnFail = options.imageOnFail;
                resetViewBeforeLoading = options.resetViewBeforeLoading;
                cacheInMemory = options.cacheInMemory;
                cacheOnDisk = options.cacheOnDisk;
                imageScaleType = options.imageScaleType;
                decodingOptions = options.decodingOptions;
                delayBeforeLoading = options.delayBeforeLoading;
                considerExifParams = options.considerExifParams;
                extraForDownloader = options.extraForDownloader;
                preProcessor = options.preProcessor;
                postProcessor = options.postProcessor;
                displayer = options.displayer;
                handler = options.handler;
                isSyncLoading = options.isSyncLoading;
                return this;
            }
    
            /** Builds configured {@link DisplayImageOptions} object */
            public DisplayImageOptions build() {
                return new DisplayImageOptions(this);
            }
        }
    
        /**
         * Creates options appropriate for single displaying:
         * <ul>
         * <li>View will <b>not</b> be reset before loading</li>
         * <li>Loaded image will <b>not</b> be cached in memory</li>
         * <li>Loaded image will <b>not</b> be cached on disk</li>
         * <li>{@link ImageScaleType#IN_SAMPLE_POWER_OF_2} decoding type will be used</li>
         * <li>{@link Bitmap.Config#ARGB_8888} bitmap config will be used for image decoding</li>
         * <li>{@link SimpleBitmapDisplayer} will be used for image displaying</li>
         * </ul>
         * <p/>
         * These option are appropriate for simple single-use image (from drawables or from Internet) displaying.
         */
        public static DisplayImageOptions createSimple() {
            return new Builder().build();
        }
    }

    参考链接

    http://blog.csdn.net/wangjinyu501/article/details/8091623

    https://github.com/nostra13/Android-Universal-Image-Loader

    http://www.intexsoft.com/blog/item/74-universal-image-loader-part-3.html

  • 相关阅读:
    Atitit 趋势管理之道 attilax著
    Atitit 循环处理的新特性 for...else...
    Atitit 2017年的技术趋势与未来的大技术趋势
    atitit 用什么样的维度看问题.docx 如何了解 看待xxx
    atitit prj mnrs 项目中的几种经理角色.docx
    Atitit IT办公场所以及度假村以及网点以及租房点建设之道 attilax总结
    Atitit 工具选型的因素与方法 attilax总结
    Atitit.团队文化建设影响组织的的一些原理 法则 定理 效应 p826.v4
    Atiitt 管理方面的误区总结 attilax总结
    Atitit 未来趋势把控的书籍 attilax总结 v3
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/5168449.html
Copyright © 2011-2022 走看看