ImageLoader詳解(簡單使用,源碼分析,策略理解)

ImageLoader詳解(簡單使用,源碼分析,策略理解)

整體流程

在這裏插入圖片描述

簡單使用

ImageLoaderConfiguration:全局配置:主要有線程類、緩存大小、磁盤大小、圖片下載與解析的配置。

DisplayImageOptions:與展示圖片相關的配置

ImageLoader:具體執行類,最終通過displayImage方法執行

//DisplayImageOptions相關設置
DisplayImageOptions options = new DisplayImageOptions.Builder().showImageOnLoading(R.drawable.loading) 
                // 設置圖片在下載期間顯示的圖片
                .showImageForEmptyUri(R.drawable.ic_launcher)
                // 設置圖片Uri爲空或是錯誤的時候顯示的圖片
                .showImageOnFail(R.drawable.error) 
                // 設置圖片加載/解碼過程中錯誤時候顯示的圖片
                .cacheInMemory(true)
                // 設置下載的圖片是否緩存在內存中
                .cacheOnDisk(true)
                // 設置下載的圖片是否緩存在SD卡中
                .considerExifParams(true) 
                // 是否考慮JPEG圖像EXIF參數(旋轉,翻轉)
                .imageScaleType(ImageScaleType.IN_SAMPLE_INT)
                // 設置圖片以如何的編碼方式顯示
                .bitmapConfig(Bitmap.Config.RGB_565)
                // 設置圖片的解碼類型
                // .decodingOptions(BitmapFactory.Options decodingOptions)
                // 設置圖片的解碼配置
                .delayBeforeLoading(0)
                // int delayInMillis爲你設置的下載前的延遲時間
                // 設置圖片加入緩存前,對bitmap進行設置
                // .preProcessor(BitmapProcessor preProcessor)
                .resetViewBeforeLoading(true)
                // 設置圖片在下載前是否重置,復位
                .displayer(new RoundedBitmapDisplayer(20))
                // 不推薦用!!!!是否設置爲圓角,弧度爲多少
                .displayer(new FadeInBitmapDisplayer(100))
                // 是否圖片加載好後漸入的動畫時間,可能會出現閃動
                .build();// 構建完成
//ImageLoaderConfiguration相關設置
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
    	// 線程池內加載的數量
    	.threadPoolSize(3)
        // 線程優先級
        .threadPriority(Thread.NORM_PRIORITY - 2)
        // 不允許緩存一張圖片的不同尺寸
        .denyCacheImageMultipleSizesInMemory()
        // 設置內存緩存,可以自定義實現
        .memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024))
        // 內存緩存最大值
        .memoryCacheSize(2 * 1024 * 1024)
        // 磁盤緩存最大值
        .diskCacheSize(50 * 1024 * 1024)
        // 磁盤緩存文件名生成器
        .diskCacheFileNameGenerator(new Md5FileNameGenerator())
        // 設置任務的執行順序
        .tasksProcessingOrder(QueueProcessingType.LIFO)
        // 緩存的文件數量
        .diskCacheFileCount(100)
        // 默認的顯示設置
        .defaultDisplayImageOptions(DisplayImageOptions.createSimple())
        // 設置加載器
        .imageDownloader(new BaseImageDownloader(context, 5 * 1000, 30 * 1000))
        // log
        .writeDebugLogs()
        // 開始構建
        .build();

//使用
ImageLoader.getInstance().init(config);
ImageLoader.getInstance().displayImage(bannerModel.getImageUrl(), imageView,options);

源碼解析

包結構大致如下:僅對部分功能講解

在這裏插入圖片描述

download包:封裝了圖片下載相關的方式

//ImageDownloader類中
public static enum Scheme {
    HTTP("http"),
    HTTPS("https"),
    FILE("file"),
    CONTENT("content"),
    ASSETS("assets"),
    DRAWABLE("drawable"),
    UNKNOWN("");

該接口中可以看到可以從網絡,文件,content,assets目錄,drawable目錄去下載文件

BaseImageDownloader爲具體實現類(SlowNetworkImageDownloader NetworkDeniedImageDownloader在其他目錄,後面再講)

public InputStream getStream(String imageUri, Object extra) throws IOException {
    switch(Scheme.ofUri(imageUri)) {
    case HTTP:
    case HTTPS:
            //網絡資源從網絡下載,重定向小於5次
        return this.getStreamFromNetwork(imageUri, extra);
    case FILE:
            //File資源從文件下載(爲視頻URi時使用視頻縮略圖)
        return this.getStreamFromFile(imageUri, extra);
    case CONTENT:
   //content資源通過contentresolver獲得(爲視頻URi時使用視頻縮略圖,聯繫人的URI獲取聯繫人縮略圖)
        return this.getStreamFromContent(imageUri, extra);
    case ASSETS://Assert,drawable 資源正常獲取。
        return this.getStreamFromAssets(imageUri, extra);
    case DRAWABLE:
        return this.getStreamFromDrawable(imageUri, extra);
    case UNKNOWN:
    default:
        return this.getStreamFromOtherSource(imageUri, extra);
    }
}

display包:封裝簡單的對展示圖片的屬性的處理(變圓形,圓角矩形,漸入動畫,內陰影等)

通過實現自定義的Drawable,重寫draw方法,使用BitmapShader將bitmap與paint綁定,將其繪製在自定義的不同形狀的Canvas上,重寫onBoundsChange方法,來控制繪製區域的大小,使其更合理的展示出來。

imageWare包:對ImageView的一層包裝,方便內部擴展,如動畫的效果。

protected void setImageDrawableInto(Drawable drawable, View view) {
    ((ImageView)view).setImageDrawable(drawable);
    if (drawable instanceof AnimationDrawable) {
        //此處開始動畫
        ((AnimationDrawable)drawable).start();
    }
}

相關策略

網絡下載策略

ImageLoader對不同的網絡狀態下處理下載策略是不同的,主要分爲三種網絡(正常、慢速、無網絡權限),針對三種網絡,實現了三種策略(BaseImageDownloader,SlowNetworkImageDownloader,NetworkDeniedImageDownloader )

BaseImageDownloader如上描述,處理正常網絡情況以及其他的情況

SlowNetworkImageDownloader

private static class SlowNetworkImageDownloader implements ImageDownloader {
    private final ImageDownloader wrappedDownloader;

    public SlowNetworkImageDownloader(ImageDownloader wrappedDownloader) {
        this.wrappedDownloader = wrappedDownloader;
    }

    public InputStream getStream(String imageUri, Object extra) throws IOException {
        InputStream imageStream = this.wrappedDownloader.getStream(imageUri, extra);
        switch(Scheme.ofUri(imageUri)) {
        case HTTP:
        case HTTPS:
            return new FlushedInputStream(imageStream);
        default:
            return imageStream;
        }
    }
}

//FlushedInputStream類
public class FlushedInputStream extends FilterInputStream {
    public FlushedInputStream(InputStream inputStream) {
        super(inputStream);
    }

    public long skip(long n) throws IOException {
        long totalBytesSkipped;
        long bytesSkipped;
        for(totalBytesSkipped = 0L; totalBytesSkipped < n; totalBytesSkipped += bytesSkipped) {
            bytesSkipped = this.in.skip(n - totalBytesSkipped);
            if (bytesSkipped == 0L) {
                int by_te = this.read();
                if (by_te < 0) {
                    break;
                }
                bytesSkipped = 1L;
            }
        }
        return totalBytesSkipped;
    }
}

可見慢網情況下使用了FilterInputStream,重寫了skip方法,具體的好處大家可以百度,這裏就不過多解釋了

NetworkDeniedImageDownloader

private static class NetworkDeniedImageDownloader implements ImageDownloader {
    private final ImageDownloader wrappedDownloader;

    public NetworkDeniedImageDownloader(ImageDownloader wrappedDownloader) {
        this.wrappedDownloader = wrappedDownloader;
    }

    public InputStream getStream(String imageUri, Object extra) throws IOException {
        switch(Scheme.ofUri(imageUri)) {
        case HTTP:
        case HTTPS:
            throw new IllegalStateException();
        default:
            return this.wrappedDownloader.getStream(imageUri, extra);
        }
    }
}

可見,在無權限的情況下,訪問網絡的直接拋異常,其他類型的則不影響處理

線程池策略

未完待續。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章