基於Glide4.7.1二次封裝

豌豆射手_BiuBiu發表於2018-08-21

github

image.png

使用方法

     String url="https://upload-images.jianshu.io/upload_images/5363507-476c8bb17b124d22.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240";
        //        //圓形圖片
        ImageLoaderV4.getInstance().displayCircleImage(this, "http://imgsrc.baidu.com/imgad/pic/item/267f9e2f07082838b5168c32b299a9014c08f1f9.jpg", mImageView_1, R.mipmap.ic_launcher_round);
        //圓角圖片
        ImageLoaderV4.getInstance().displayRoundImage(this, "http://imgsrc.baidu.com/imgad/pic/item/267f9e2f07082838b5168c32b299a9014c08f1f9.jpg", mImageView_2, R.mipmap.ic_launcher_round, 40);
        //模糊圖片
        ImageLoaderV4.getInstance().displayBlurImage(this, "http://imgsrc.baidu.com/imgad/pic/item/267f9e2f07082838b5168c32b299a9014c08f1f9.jpg", mImageView_3, R.mipmap.ic_launcher_round, 10);

        //本地圖片 不做處理
        ImageLoaderV4.getInstance().displayImageInResource(this, R.mipmap.test, mImageView_4);
        // TODO: 2018/4/20  以下的三種不介意使用,需要解決一些問題  start
        //本地圖片,模糊處理
        ImageLoaderV4.getInstance().displayImageInResource(this, R.mipmap.test, mImageView_5, new BlurBitmapTranformation( 200));
        //本地圖片,裁圓角處理
        ImageLoaderV4.getInstance().displayImageInResource(this, R.mipmap.test, mImageView_6, new GlideCircleTransformation());
        //四周倒角處理
        ImageLoaderV4.getInstance().displayImageInResource(this, R.mipmap.test, mImageView_7, new RoundBitmapTranformation( 40));
        // TODO: 2018/4/20  以上的三種不介意使用,需要解決一些問題  start


        //使用的是另外一種方法,指定傳入的那種的方法 ,還可以不斷的擴充套件,不斷的擴充套件,這是Gilded提供的一些操作,牛逼 ,牛逼 這是對本地圖片的操作
        ImageLoaderV4.getInstance().displayImageInResourceTransform(this, R.mipmap.test, mImageView_8, new CenterInside(), R.mipmap.test);
        ImageLoaderV4.getInstance().displayImageInResourceTransform(this, R.mipmap.test, mImageView_9, new CircleCrop(), R.mipmap.test);
        ImageLoaderV4.getInstance().displayImageInResourceTransform(this, R.mipmap.test, mImageView_10, new FitCenter(), R.mipmap.test);
        ImageLoaderV4.getInstance().displayImageInResourceTransform(this, R.mipmap.test, mImageView_11, new RoundedCorners(10), R.mipmap.test);

       //對網路圖片的操作
        ImageLoaderV4.getInstance().displayImageByNet(this,url,mImageView_12, R.mipmap.test,new CenterInside());
        ImageLoaderV4.getInstance().displayImageByNet(this,url,mImageView_13, R.mipmap.test,new CircleCrop());
        ImageLoaderV4.getInstance().displayImageByNet(this,url,mImageView_14, R.mipmap.test,new FitCenter());
        ImageLoaderV4.getInstance().displayImageByNet(this,url,mImageView_15, R.mipmap.test,new RoundedCorners(10));


複製程式碼

實現效果:監聽圖片的下載進度,注意事項需要在監聽返回鍵的時候,取消請求

 ImageLoaderV4.getInstance().disPlayImageProgress(this, "http://img.zcool.cn/community/0142135541fe180000019ae9b8cf86.jpg@1280w_1l_2o_100sh.png", mImageView_8, R.mipmap.test, R.mipmap.test, new OnGlideImageViewListener() {
            @Override
            public void onProgress(int percent, boolean isDone, GlideException exception) {
                System.out.println("shiming percent="+percent);
                System.out.println("shiming isDone="+isDone);
                mProgress.setText("我在主執行緒,進度是多少=="+percent+"%");

                if (isDone){
                    mProgress.setText("我在主執行緒,進度是多少==100%");
                }
            }
        });


        ImageLoaderV4.getInstance().disPlayImageProgressByOnProgressListener(this, "http://img.zcool.cn/community/0142135541fe180000019ae9b8cf86.jpg@1280w_1l_2o_100sh.png", mImageView_7, R.mipmap.test, R.mipmap.test, new OnProgressListener() {
            @Override
            public void onProgress(String imageUrl, long bytesRead, long totalBytes, boolean isDone, GlideException exception) {
                System.out.println("shiming bytesRead="+bytesRead);
                System.out.println("shiming totalBytes="+totalBytes);
                mProgress7.setText("我在主執行緒,進度是多少==+bytesRead"+bytesRead+"totalBytes="+totalBytes);

                if (isDone){
                    mProgress7.setText("我在主執行緒,進度是多少==100%");
                }
            }
        });
複製程式碼

image.png

image.png
使用內部提供的圖片處理
image.png
加入依賴

 compile 'com.github.bumptech.glide:glide:4.7.1'
 annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
 compile "com.github.bumptech.glide:okhttp3-integration:4.5.0"
複製程式碼

構建AppGlideModule

image.png
初始化registerComponents()方法,使用okhttp加入攔截器

  /**
     OkHttp 是一個底層網路庫(相較於 Cronet 或 Volley 而言),儘管它也包含了 SPDY 的支援。
     OkHttp 與 Glide 一起使用可以提供可靠的效能,並且在載入圖片時通常比 Volley 產生的垃圾要少。
     對於那些想要使用比 Android 提供的 HttpUrlConnection 更 nice 的 API,
      或者想確保網路層程式碼不依賴於 app 安裝的裝置上 Android OS 版本的應用,OkHttp 是一個合理的選擇。
      如果你已經在 app 中某個地方使用了 OkHttp ,這也是選擇繼續為 Glide 使用 OkHttp 的一個很好的理由,就像選擇其他網路庫一樣。
     新增 OkHttp 整合庫的 Gradle 依賴將使 Glide 自動開始使用 OkHttp 來載入所有來自 http 和 https URL 的圖片
     * @param context
     * @param glide
     * @param registry
     */
    @Override
    public void registerComponents(Context context, Glide glide, Registry registry) {
        super.registerComponents(context, glide, registry);
        registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(ProgressManager.getOkHttpClient()));
    }
複製程式碼

預設情況下,Glide使用 LruResourceCache , 這是 MemoryCache 介面的一個預設實現,使用固定大小的記憶體和 LRU 演算法。 LruResourceCache 的大小由 Glide 的 MemorySizeCalculator 類來決定,這個類主要關注裝置的記憶體型別,裝置 RAM 大小,以及螢幕解析度。應用程式可以自定義 MemoryCache 的大小, 具體是在它們的 AppGlideModule 中使用applyOptions(Context, GlideBuilder) 方法配置 MemorySizeCalculator

   //Glide會自動合理分配記憶體快取,但是也可以自己手動分配。
//    @Override
//    public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
//        super.applyOptions(context, builder);
//        //1、setMemoryCacheScreens設定MemoryCache應該能夠容納的畫素值的裝置螢幕數,
//        // 說白了就是快取多少屏圖片,預設值是2。
//        //todo 建議不要設定,使用glide 預設
////        MemorySizeCalculator calculator = new MemorySizeCalculator.Builder(context)
////                .setMemoryCacheScreens(2)
////                .build();
////        builder.setMemoryCache(new LruResourceCache(calculator.getMemoryCacheSize()));
//
//        //2。也可以直接覆寫快取大小:todo 建議不要設定,使用glide 預設
////        int memoryCacheSizeBytes = 1024 * 1024 * 20; // 20mb
////        builder.setMemoryCache(new LruResourceCache(memoryCacheSizeBytes));
////        3.甚至可以提供自己的 MemoryCache 實現:
////        builder.setMemoryCache(new YourAppMemoryCacheImpl());
//    }
複製程式碼

Bitmap 池Glide 使用 LruBitmapPool 作為預設的 BitmapPool LruBitmapPool 是一個記憶體中的固定大小的 BitmapPool,使用 LRU 演算法清理。預設大小基於裝置的解析度和密度,同時也考慮記憶體類和 isLowRamDevice 的返回值。 具體的計算通過 Glide 的 MemorySizeCalculator 來完成,與 Glide 的 MemoryCache 的大小檢測方法相似。

//    @Override
//    public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
//        super.applyOptions(context, builder);
//    //1 .應用可以在它們的 AppGlideModule 中定製 [BitmapPool] 的尺寸,
//        // 使用 applyOptions(Context, GlideBuilder) 方法並配置 MemorySizeCalculator
////        MemorySizeCalculator calculator = new MemorySizeCalculator.Builder(context)
////                .setBitmapPoolScreens(3)
////                .build();
////        builder.setBitmapPool(new LruBitmapPool(calculator.getBitmapPoolSize()));
//
//        //2、應用也可以直接複寫這個池的大小:
//
////        int bitmapPoolSizeBytes = 1024 * 1024 * 30; // 30mb
////        builder.setBitmapPool(new LruBitmapPool(bitmapPoolSizeBytes));
//
//
//        //3、甚至可以提供 BitmapPool 的完全自定義實現:
//
////        builder.setBitmapPool(new YourAppBitmapPoolImpl());
//    }
複製程式碼

磁碟快取Glide 使用 DiskLruCacheWrapper 作為預設的 磁碟快取 . DiskLruCacheWrapper 是一個使用 LRU 演算法的固定大小的磁碟快取。預設磁碟大小為 250 MB , 位置是在應用的 快取資料夾 中的一個 特定目錄 。

  @Override
    public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
        super.applyOptions(context, builder);
        //假如應用程式展示的媒體內容是公開的(從無授權機制的網站上載入,或搜尋引擎等),
        //那麼應用可以將這個快取位置改到外部儲存:
//        builder.setDiskCache(new ExternalDiskCacheFactory(context));


         //2、無論使用內部或外部磁碟快取,應用程式都可以改變磁碟快取的大小:
//        int diskCacheSizeBytes = 1024 *1024 *100;  //100 MB
//        builder.setDiskCache(new InternalDiskCacheFactory(context, diskCacheSizeBytes));


        //3、應用程式還可以改變快取資料夾在外存或記憶體上的名字:
//        int diskCacheSizeBytes = 1024 * 1024 *100; // 100 MB
//        builder.setDiskCache(new InternalDiskCacheFactory(context, cacheFolderName, diskCacheSizeBytes));


        //4、應用程式還可以自行選擇 DiskCache 介面的實現,並提供自己的 DiskCache.Factory 來建立快取。
        // Glide 使用一個工廠介面來在後臺執行緒中開啟 磁碟快取 ,
        // 這樣方便快取做諸如檢查路徑存在性等的IO操作而不用觸發 嚴格模式 。
//        builder.setDiskCache(new DiskCache.Factory() {
//            @Override
//            public DiskCache build() {
//                return new YourAppCustomDiskCache();
//            }
//        });
        
    }
複製程式碼
/**
 * author: Created by shiming on 2018/4/20 15:13
 * mailbox:lamshiming@sina.com
 磁碟快取
 Glide 使用 DiskLruCacheWrapper 作為預設的 磁碟快取 。
 DiskLruCacheWrapper 是一個使用 LRU 演算法的固定大小的磁碟快取。預設磁碟大小為 250 MB ,
 位置是在應用的 快取資料夾 中的一個 特定目錄 。
 假如應用程式展示的媒體內容是公開的(從無授權機制的網站上載入,或搜尋引擎等),
 那麼應用可以將這個快取位置改到外部儲存:
 */

class ExternalDiskCacheFactory implements DiskCache.Factory {
    public ExternalDiskCacheFactory(Context context) {
    }

    @Nullable
    @Override
    public DiskCache build() {
        return null;
    }
}
複製程式碼

為了維持對 Glide v3 的 GlideModules 的向後相容性, Glide 仍然會解析應用程式和所有被包含的庫中的 AndroidManifest.xml 檔案, 幷包含在這些清單中列出的舊 GlideModules 模組類。如果你已經遷移到 Glide v4 的 AppGlideModule 和 LibraryGlideModule ,你可以完全禁用清單解析。 這樣可以改善 Glide 的初始啟動時間,並避免嘗試解析後設資料時的一些潛在問題。要禁用清單解析, 請在你的 AppGlideModule 實現中複寫 isManifestParsingEnabled() 方法:

    @Override
    public boolean isManifestParsingEnabled() {
        return false;
    }
複製程式碼

IImageLoaderClient介面


/**
 * Created by shiming on 2016/10/26.
 */

public interface IImageLoaderClient {
    public void init(Context context);

    public void destroy(Context context);

    public File getCacheDir(Context context);

    public void clearMemoryCache(Context context);

    public void clearDiskCache(Context context);

    public Bitmap getBitmapFromCache(Context context, String url);

    public void getBitmapFromCache(Context context, String url, IGetBitmapListener listener);

    public void displayImage(Context context, int resId, ImageView imageView);

    public void displayImage(Context context, String url, ImageView imageView);

    public void displayImage(Context context, String url, ImageView imageView, boolean isCache);

    public void displayImage(Fragment fragment, String url, ImageView imageView);

    public void displayImage(Context context, String url, ImageView imageView, int defRes);

    public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes);

    public void displayImage(Context context, String url, ImageView imageView, int defRes, BitmapTransformation transformations);

    public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes, BitmapTransformation transformations);

    public void displayImage(Context context, String url, ImageView imageView, int defRes, ImageSize size);

    public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes, ImageSize size);

    public void displayImage(Context context, String url, ImageView imageView, int defRes, boolean cacheInMemory);

    public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes, boolean cacheInMemory);


    public void displayImage(Context context, String url, ImageView imageView, IImageLoaderListener listener);

    public void displayImage(Fragment fragment, String url, ImageView imageView, IImageLoaderListener listener);

    public void displayImage(Context context, String url, ImageView imageView, int defRes, IImageLoaderListener listener);

    public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes, IImageLoaderListener listener);


    public void displayCircleImage(Context context, String url, ImageView imageView, int defRes);

    public void displayCircleImage(Fragment fragment, String url, ImageView imageView, int defRes);

    public void displayRoundImage(Context context, String url, ImageView imageView, int defRes, int radius);

    public void displayRoundImage(Fragment fragment, String url, ImageView imageView, int defRes, int radius);

    public void displayBlurImage(Context context, String url, int blurRadius, IGetDrawableListener listener);

    public void displayBlurImage(Context context, String url, ImageView imageView, int defRes, int blurRadius);

    public void displayBlurImage(Context context, int resId, ImageView imageView, int blurRadius);

    public void displayBlurImage(Fragment fragment, String url, ImageView imageView, int defRes, int blurRadius);

    public void displayImageInResource(Context context, int resId, ImageView imageView);

    public void displayImageInResource(Fragment fragment, int resId, ImageView imageView);

    public void displayImageInResource(Context context, int resId, ImageView imageView, BitmapTransformation transformations);

    public void displayImageInResource(Fragment fragment, int resId, ImageView imageView, BitmapTransformation transformations);

    public void displayImageInResource(Context context, int resId, ImageView imageView, int defRes);

    public void displayImageInResource(Fragment fragment, int resId, ImageView imageView, int defRes);

    public void displayImageInResource(Context context, int resId, ImageView imageView, int defRes, BitmapTransformation transformations);

    public void displayImageInResource(Fragment fragment, int resId, ImageView imageView, int defRes, BitmapTransformation transformations);


    //add shiming   2018.4.20 transformation 需要裝換的那種影象的風格,錯誤圖片,或者是,正在載入中的錯誤圖
    public void displayImageInResourceTransform(Activity activity, int resId, ImageView imageView, Transformation transformation, int errorResId);
    public void displayImageInResourceTransform(Context context, int resId, ImageView imageView, Transformation transformation, int errorResId);
    public void displayImageInResourceTransform(Fragment fragment, int resId, ImageView imageView, Transformation transformation, int errorResId);

    //這是對網路圖片,進行的圖片操作,使用的glide中的方法
    public void displayImageByNet(Context context, String url, ImageView imageView, int defRes,Transformation transformation);
    public void displayImageByNet(Fragment fragment, String url, ImageView imageView, int defRes,Transformation transformation);
    public void displayImageByNet(Activity activity, String url, ImageView imageView, int defRes,Transformation transformation);


    /**
     *  停止圖片的載入,對某一個的Activity
     * @hide
     */
    public void clear(Activity activity,ImageView imageView);
    /**
     * 停止圖片的載入,context
     * {@hide}
     */
    public void clear(Context context,ImageView imageView);
    /**
     * 停止圖片的載入,fragment
     * {@hide}
     */
    public void clear(Fragment fragment,ImageView imageView);


    //如果需要的話,需要指定載入中,或者是失敗的圖片
    public void displayImageByDiskCacheStrategy(Fragment fragment, String url, DiskCacheStrategy diskCacheStrategy,ImageView imageView);
    public void displayImageByDiskCacheStrategy(Activity activity, String url, DiskCacheStrategy diskCacheStrategy,ImageView imageView);
    public void displayImageByDiskCacheStrategy(Context context, String url, DiskCacheStrategy diskCacheStrategy,ImageView imageView);
    //某些情形下,你可能希望只要圖片不在快取中則載入直接失敗(比如省流量模式)
    public void disPlayImageOnlyRetrieveFromCache(Fragment fragment,String url,ImageView imageView);
    public void disPlayImageOnlyRetrieveFromCache(Activity activity,String url,ImageView imageView);
    public void disPlayImageOnlyRetrieveFromCache(Context context,String url,ImageView imageView);



    /**
     *如果你想確保一個特定的請求跳過磁碟和/或記憶體快取(比如,圖片驗證碼 –)
     * @param fragment
     * @param url
     * @param imageView
     * @param skipflag  是否跳過記憶體快取
     * @param diskCacheStratey  是否跳過磁碟快取
     */
    public void disPlayImageSkipMemoryCache(Fragment fragment,String url,ImageView imageView,boolean skipflag,boolean diskCacheStratey);
    public void disPlayImageSkipMemoryCache(Activity activity,String url,ImageView imageView,boolean skipflag,boolean diskCacheStratey);
    public void disPlayImageSkipMemoryCache(Context context,String url,ImageView imageView,boolean skipflag,boolean diskCacheStratey);

    /**
     * 知道這個圖片會載入失敗,那麼的話,我們可以重新載入
     * @param fragment
     * @param url
     * @param fallbackUrl
     * @param imageView
     */
    //從 Glide 4.3.0 開始,你可以很輕鬆地使用 .error() 方法。這個方法接受一個任意的 RequestBuilder,它會且只會在主請求失敗時開始一個新的請求:
    public void disPlayImageErrorReload(Fragment fragment,String url,String fallbackUrl,ImageView imageView);
    public void disPlayImageErrorReload(Activity activity,String url,String fallbackUrl,ImageView imageView);
    public void disPlayImageErrorReload(Context context,String url,String fallbackUrl,ImageView imageView);


    /**
     未來 Glide 將預設載入硬體點陣圖而不需要額外的啟用配置,只保留禁用的選項 現在已經預設開啟了這個配置,但是在有些情況下需要關閉
     所以提供了以下的方法,禁用硬體點陣圖 disallowHardwareConfig
     * @param fragment
     * @param url
     * @param imageView
     */
//    哪些情況不能使用硬體點陣圖?
//    在視訊記憶體中儲存畫素資料意味著這些資料不容易訪問到,在某些情況下可能會發生異常。已知的情形列舉如下:
//    在 Java 中讀寫畫素資料,包括:
//    Bitmap#getPixel
//    Bitmap#getPixels
//    Bitmap#copyPixelsToBuffer
//    Bitmap#copyPixelsFromBuffer
//    在本地 (native) 程式碼中讀寫畫素資料
//    使用軟體畫布 (software Canvas) 渲染硬體點陣圖:
//    Canvas canvas = new Canvas(normalBitmap)
//canvas.drawBitmap(hardwareBitmap, 0, 0, new Paint());
//    在繪製點陣圖的 View 上使用軟體層 (software layer type) (例如,繪製陰影)
//    ImageView imageView = …
//            imageView.setImageBitmap(hardwareBitmap);
//imageView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
//    開啟過多的檔案描述符 . 每個硬體點陣圖會消耗一個檔案描述符。
// 這裡存在一個每個程式的檔案描述符限制 ( Android O 及更早版本一般為 1024,在某些 O-MR1 和更高的構建上是 32K)。
// Glide 將嘗試限制分配的硬體點陣圖以保持在這個限制以內,但如果你已經分配了大量的檔案描述符,這可能是一個問題。
//    需要ARGB_8888 Bitmaps 作為前置條件
//    在程式碼中觸發截圖操作,它會嘗試使用 Canvas 來繪製檢視層級。
//    作為一個替代方案,在 Android O 以上版本你可以使用 PixelCopy.
//   共享元素過渡 (shared element transition)(OMR1已修復)
    public void disPlayImagedisallowHardwareConfig(Fragment fragment,String url,ImageView imageView);
    public void disPlayImagedisallowHardwareConfig(Activity activity,String url,ImageView imageView);
    public void disPlayImagedisallowHardwareConfig(Context context,String url,ImageView imageView);

    //監聽圖片的下載進度,是否完成,百分比 也可以載入本地圖片,擴張一下
    public void disPlayImageProgress(Context context,String url,ImageView imageView,int placeholderResId,int errorResId,OnGlideImageViewListener listener);
    public void disPlayImageProgress(Activity activity,String url,ImageView imageView,int placeholderResId,int errorResId,OnGlideImageViewListener listener);
    public void disPlayImageProgress(Fragment fragment,String url,ImageView imageView,int placeholderResId,int errorResId,OnGlideImageViewListener listener);

    public void disPlayImageProgressByOnProgressListener(Context context,String url,ImageView imageView,int placeholderResId,int errorResId, OnProgressListener onProgressListener);
    public void disPlayImageProgressByOnProgressListener(Activity activity,String url,ImageView imageView,int placeholderResId,int errorResId, OnProgressListener onProgressListener);
    public void disPlayImageProgressByOnProgressListener(Fragment fragment,String url,ImageView imageView,int placeholderResId,int errorResId, OnProgressListener onProgressListener);



//    TransitionOptions 用於給一個特定的請求指定過渡。
//    每個請求可以使用 RequestBuilder 中的 transition()
//    方法來設定 TransitionOptions 。還可以通過使用
//    BitmapTransitionOptions 或 DrawableTransitionOptions
//    來指定型別特定的過渡動畫。對於 Bitmap 和 Drawable
//    之外的資源型別,可以使用 GenericTransitionOptions。 Glide v4 將不會預設應用交叉淡入或任何其他的過渡效果。每個請求必須手動應用過渡。
    public void displayImageByTransition(Context context, String url, TransitionOptions transitionOptions, ImageView imageView);
    public void displayImageByTransition(Activity activity, String url, TransitionOptions transitionOptions, ImageView imageView);
    public void displayImageByTransition(Fragment fragment, String url, TransitionOptions transitionOptions, ImageView imageView);

    //失去焦點,建議實際的專案中少用,取消求情
    public void glidePauseRequests(Context context);
    public void glidePauseRequests(Activity activity);
    public void glidePauseRequests(Fragment fragment);

    //獲取焦點,建議實際的專案中少用
    public void glideResumeRequests(Context context);
    public void glideResumeRequests(Activity activity);
    public void glideResumeRequests(Fragment fragment);
    //載入縮圖圖     int thumbnailSize = 10;//越小,圖片越小,低網路的情況,圖片越小
    //GlideApp.with(this).load(urlnoData).override(thumbnailSize))// API 來強制 Glide 在縮圖請求中載入一個低解析度影象
    public void displayImageThumbnail(Context context,String url,String backUrl,int thumbnailSize,ImageView imageView);
    public void displayImageThumbnail(Activity activity,String url,String backUrl,int thumbnailSize,ImageView imageView);
    public void displayImageThumbnail(Fragment fragment,String url,String backUrl,int thumbnailSize,ImageView imageView);
    //如果沒有兩個url的話,也想,記載一個縮圖
    public void displayImageThumbnail(Fragment fragment,String url,float thumbnailSize,ImageView imageView);
    public void displayImageThumbnail(Activity activity,String url,float thumbnailSize,ImageView imageView);
    public void displayImageThumbnail(Context context,String url,float thumbnailSize,ImageView imageView);
}

複製程式碼

GlideImageLoaderClient實現類

package code.shiming.com.imageloader471;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.widget.ImageView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.TransitionOptions;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.Transformation;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;

import java.io.File;

import code.shiming.com.imageloader471.listener.IGetBitmapListener;
import code.shiming.com.imageloader471.listener.IGetDrawableListener;
import code.shiming.com.imageloader471.listener.IImageLoaderListener;
import code.shiming.com.imageloader471.listener.ImageSize;
import code.shiming.com.imageloader471.okhttp.OnGlideImageViewListener;
import code.shiming.com.imageloader471.okhttp.OnProgressListener;
import code.shiming.com.imageloader471.okhttp.ProgressManager;
import code.shiming.com.imageloader471.tranform.BlurBitmapTranformation;
import code.shiming.com.imageloader471.tranform.GlideCircleTransformation;
import code.shiming.com.imageloader471.tranform.RoundBitmapTranformation;


/**
* Created by shiming on 2016/10/26.
* des:
* with(Context context). 使用Application上下文,Glide請求將不受Activity/Fragment生命週期控制。
 with(Activity activity).使用Activity作為上下文,Glide的請求會受到Activity生命週期控制。
 with(FragmentActivity activity).Glide的請求會受到FragmentActivity生命週期控制。
 with(android.app.Fragment fragment).Glide的請求會受到Fragment 生命週期控制。
 with(android.support.v4.app.Fragment fragment).Glide的請求會受到Fragment生命週期控制。
*/

public class GlideImageLoaderClient implements IImageLoaderClient {

  private static final String TAG ="GlideImageLoaderClient";

  @Override
  public void init(Context context) {
  }
  @Override
  public void destroy(Context context) {
      clearMemoryCache(context);
  }
  @Override
  public File getCacheDir(Context context) {
      return Glide.getPhotoCacheDir(context);
  }

  /**
   * 使用ui執行緒
   * @param context
   */
  @UiThread
  @Override
  public void clearMemoryCache(Context context) {
      GlideApp.get(context).clearMemory();
  }

  @SuppressLint("StaticFieldLeak")
  @Override
  public void clearDiskCache(final Context context) {
      new AsyncTask<Void, Void, Void> (){
          @Override
          protected Void doInBackground(Void... params) {
              //必須在子執行緒中  This method must be called on a background thread.
              Glide.get(context).clearDiskCache();
              return null;
          }
      };
  }

  @Override
  public Bitmap getBitmapFromCache(Context context, String url) {
      throw new UnsupportedOperationException("glide 不支援同步 獲取快取中 bitmap");
  }
  /**
   * 獲取快取中的圖片
   * @param context
   * @param url
   * @param listener
   */
  @Override
  public void getBitmapFromCache(Context context, String url, final IGetBitmapListener listener) {
     GlideApp.with(context).asBitmap().load(url).into(new SimpleTarget<Bitmap>() {
         @Override
         public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
             if (listener != null) {
                 listener.onBitmap(resource);
             }
         }
     });
  }

  /**
   *
   預設的策略是DiskCacheStrategy.AUTOMATIC
   DiskCacheStrategy.ALL 使用DATA和RESOURCE快取遠端資料,僅使用RESOURCE來快取本地資料。
   DiskCacheStrategy.NONE 不使用磁碟快取
   DiskCacheStrategy.DATA 在資源解碼前就將原始資料寫入磁碟快取
   DiskCacheStrategy.RESOURCE 在資源解碼後將資料寫入磁碟快取,即經過縮放等轉換後的圖片資源。
   DiskCacheStrategy.AUTOMATIC 根據原始圖片資料和資源編碼策略來自動選擇磁碟快取策略。
   * @param context  上下文
   * @param resId  id
   * @param imageView into
    */
  //DiskCacheStrategy.SOURCE:快取原始資料 DiskCacheStrategy.DATA對應Glide 3中的DiskCacheStrategy.SOURCE
  @Override
  public void displayImage(Context context, int resId, ImageView imageView) {
      //設定快取策略快取原始資料  Saves just the original data to cache
      GlideApp.with(context).load(resId).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).into(imageView);
  }

  /**
   *
   * @param context
   * @param url url
   * @param imageView in
   */
  @Override
  public void displayImage(Context context, String url, ImageView imageView) {
      GlideApp.with(context).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).into(imageView);
  }

  /**
   *
   * @param context
   * @param url
   * @param imageView
   * @param isCache 是否是快取 如果是:快取策略快取原始資料  不是的話 :快取策略DiskCacheStrategy.NONE:什麼都不快取
   */
  @Override
  public void displayImage(Context context, String url, ImageView imageView, boolean isCache) {
      GlideApp.with(context).load(url).skipMemoryCache(isCache).diskCacheStrategy(isCache ? DiskCacheStrategy.AUTOMATIC : DiskCacheStrategy.NONE).into(imageView);
  }

  /**
   *
   * @param fragment 繫結生命週期
   * @param url
   * @param imageView
   */
  @Override
  public void displayImage(Fragment fragment, String url, ImageView imageView) {
      GlideApp.with(fragment).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).into(imageView);
  }

  /**
   * 使用.placeholder()方法在某些情況下會導致圖片顯示的時候出現圖片變形的情況
   * 這是因為Glide預設開啟的crossFade動畫導致的TransitionDrawable繪製異常
   * @param context
   * @param url
   * @param imageView
   * @param defRes defRes 可以是個new ColorDrawable(Color.BLACK) 也可以是張圖片
   */
  //預設為200  時間有點長  ,工程中要修改下,設定一個載入失敗和載入中的動畫過渡,V4.0的使用的方法
  @Override
  public void displayImage(Context context, String url, ImageView imageView, int defRes) {
      GlideApp.with(context).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).transition(new DrawableTransitionOptions().crossFade(200)).placeholder(defRes).error(defRes).into(imageView);
  }

  /**
   * 預設時間為200 需
   * @param fragment
   * @param url
   * @param imageView
   * @param defRes
   */
  @Override
  public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes) {
      GlideApp.with(fragment).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).transition(new DrawableTransitionOptions().crossFade(200)).placeholder(defRes).error(defRes).into(imageView);
  }

  /**
   *
   * @param context
   * @param url
   * @param imageView
   * @param defRes
   * @param transformations bitmapTransform 方法設定圖片轉換
   */

  @Override
  public void displayImage(Context context, String url, ImageView imageView, int defRes, final BitmapTransformation transformations) {
      GlideApp.with(context).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).apply(requestOptionsTransformation(defRes,defRes,transformations)).into(imageView);
  }

  @Override
  public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes, BitmapTransformation transformations) {
      GlideApp.with(fragment).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).apply(requestOptionsTransformation(defRes,defRes,transformations)).into(imageView);
  }


  /**
   * 載入原圓形圖片
   * @param context
   * @param url
   * @param imageView
   * @param defRes
   */
  public void displayImageCircle(Context context, String url, ImageView imageView, int defRes) {
      GlideApp.with(context).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).apply(circleRequestOptions(defRes,defRes)).into(imageView);

  }
  public void displayImageCircle(Fragment context, String url, ImageView imageView, int defRes) {
      GlideApp.with(context).load(url).diskCacheStrategy(DiskCacheStrategy.DATA).apply(circleRequestOptions(defRes,defRes)).into(imageView);
  }
  public RequestOptions requestOptions(int placeholderResId, int errorResId) {
      return new RequestOptions()
              .placeholder(placeholderResId)
              .error(errorResId);
  }
  public RequestOptions requestOptionsTransformation(int placeholderResId, int errorResId,BitmapTransformation bitmapTransformation) {
      return requestOptions(placeholderResId,errorResId)
              .transform(bitmapTransformation);
  }
  /**
   * 載入原圖
   * @param placeholderResId
   * @param errorResId
   * @return
   */
  public RequestOptions circleRequestOptions(int placeholderResId, int errorResId) {
      return requestOptions(placeholderResId, errorResId)
              .transform(new GlideCircleTransformation());
  }

  public RequestOptions roundRequestOptions(int placeholderResId, int errorResId,int radius) {
      return requestOptions(placeholderResId, errorResId)
              .transform(new RoundBitmapTranformation(radius));
  }
  /**
   *
   * @param context
   * @param url
   * @param imageView
   * @param defRes placeholder(int resourceId). 設定資源載入過程中的佔位Drawable  error(int resourceId).設定load失敗時顯示的Drawable
   * @param size override(int width, int height). 重新設定Target的寬高值
   */
  @Override
  public void displayImage(Context context, String url, ImageView imageView, int defRes, ImageSize size) {
      GlideApp.with(context).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).placeholder(defRes).error(defRes).override(size.getWidth(), size.getHeight()).into(imageView);
  }

  @Override
  public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes, ImageSize size) {
      GlideApp.with(fragment).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).placeholder(defRes).error(defRes).override(size.getWidth(), size.getHeight()).into(imageView);
  }

  /**
   * .skipMemoryCache( true )去特意告訴Glide跳過記憶體快取  是否跳過記憶體,還是不跳過
   * @param context
   * @param url
   * @param imageView
   * @param defRes
   * @param cacheInMemory
   */
  @Override
  public void displayImage(Context context, String url, ImageView imageView, int defRes, boolean cacheInMemory) {
      GlideApp.with(context).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).placeholder(defRes).error(defRes).skipMemoryCache(cacheInMemory).into(imageView);
  }

  @Override
  public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes, boolean cacheInMemory) {
      GlideApp.with(fragment).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).placeholder(defRes).error(defRes).skipMemoryCache(cacheInMemory).into(imageView);
  }

  /**
   * 只在需要的地方進行監聽 listener 通過自定義的介面回撥引數
   * @param context
   * @param url
   * @param imageView
   * @param listener  監聽資源載入的請求狀態 但不要每次請求都使用新的監聽器,要避免不必要的記憶體申請,
   *                  可以使用單例進行統一的異常監聽和處理
   */
  @Override
  public void displayImage(Context context, final String url, final ImageView imageView, final IImageLoaderListener listener) {
      GlideApp.with(context).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).listener(new RequestListener<Drawable>() {
          @Override
          public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
              listener.onLoadingFailed(url, imageView, e);
              Log.e(TAG, "Load failed", e);//如果關係的話,關係如何失敗
              return false;
          }

          @Override
          public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
              listener.onLoadingComplete(url, imageView);
              return false;
          }
      }).into(imageView);
  }

  @Override
  public void displayImage(Fragment fragment, final String url, final ImageView imageView, final IImageLoaderListener listener) {
      GlideApp.with(fragment).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).listener(new RequestListener<Drawable>() {
          @Override
          public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
              listener.onLoadingFailed(url, imageView, e);
              return false;
          }

          @Override
          public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
              listener.onLoadingComplete(url, imageView);
              return false;
          }
      }).into(imageView);
  }

  @Override
  public void displayImage(Context context, final String url, final ImageView imageView, int defRes, final IImageLoaderListener listener) {
      GlideApp.with(context).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).placeholder(defRes).error(defRes).listener(new RequestListener<Drawable>() {
          @Override
          public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
              listener.onLoadingFailed(url, imageView, e);
              return false;
          }

          @Override
          public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
              listener.onLoadingComplete(url, imageView);
              return false;
          }
      }).into(imageView);
  }

  @Override
  public void displayImage(Fragment fragment, final String url, final ImageView imageView, int defRes, final IImageLoaderListener listener) {
      GlideApp.with(fragment).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).listener(new RequestListener<Drawable>() {
          @Override
          public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
              listener.onLoadingFailed(url, imageView, e);
              return false;
          }

          @Override
          public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
              listener.onLoadingComplete(url, imageView);
              return false;
          }
      }).into(imageView);
  }

  /**
   * 圓形圖片的裁剪
   * @param context
   * @param url
   * @param imageView
   * @param defRes
   */
  @Override
  public void displayCircleImage(Context context, String url, ImageView imageView, int defRes) {
      GlideApp.with(context).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).apply(circleRequestOptions(defRes,defRes)).into(imageView);
  }

  @Override
  public void displayCircleImage(Fragment fragment, String url, ImageView imageView, int defRes) {
      GlideApp.with(fragment).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).apply(circleRequestOptions(defRes,defRes)).into(imageView);
  }


  public void displayCircleImage(Activity fragment, String url, ImageView imageView, int defRes) {
      GlideApp.with(fragment).load(url).diskCacheStrategy(DiskCacheStrategy.DATA).apply(circleRequestOptions(defRes,defRes)).into(imageView);
  }
  /**
   *
   * @param context
   * @param url
   * @param imageView
   * @param defRes
   * @param radius 倒圓角的圖片 需要傳入需要radius  越大的話,倒角越明顯
   */
  @Override
  public void displayRoundImage(Context context, String url, ImageView imageView, int defRes, int radius) {
      GlideApp.with(context).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).apply(roundRequestOptions(defRes,defRes,radius)).into(imageView);
  }

  @Override
  public void displayRoundImage(Fragment fragment, String url, ImageView imageView, int defRes, int radius) {
      GlideApp.with(fragment).load(url).diskCacheStrategy(DiskCacheStrategy.DATA).apply(roundRequestOptions(defRes,defRes,radius)).into(imageView);
  }
  /**
   *
   * @param context
   * @param url
   * @param blurRadius 模糊的程度 ,數字越大越模糊
   * @param listener 介面回撥需要拿到drawable
   */
  @Override
  public void displayBlurImage(Context context, String url, int blurRadius, final IGetDrawableListener listener) {
      GlideApp.with(context).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).into(new SimpleTarget<Drawable>() {
          @Override
          public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
              if ( listener != null ) {
                  listener.onDrawable( resource );
              }
          }
      });
  }

  /**
   * 不需要關係此模糊圖的drawable
   * @param context
   * @param url
   * @param imageView
   * @param defRes
   * @param blurRadius
   */
  @Override
  public void displayBlurImage(Context context, String url, ImageView imageView, int defRes, int blurRadius) {
      GlideApp.with(context).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).apply(blurRequestOptions(defRes,defRes,blurRadius)).into(imageView);
  }

  private RequestOptions blurRequestOptions(int defRes, int defRes1, int blurRadius) {
      return requestOptions(defRes, defRes1)
              .transform(new BlurBitmapTranformation(blurRadius));
  }

  @Override
  public void displayBlurImage(Context context, int resId, ImageView imageView, int blurRadius) {
      GlideApp.with(context).load(resId).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).apply(blurRequestOptions(resId,resId,blurRadius)).into(imageView);
  }

  @Override
  public void displayBlurImage(Fragment fragment, String url, ImageView imageView, int defRes, int blurRadius) {
      GlideApp.with(fragment).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).apply(blurRequestOptions(defRes,defRes,blurRadius)).into(imageView);
  }

  /**
   *  載入資原始檔
   * @param context
   * @param resId
   * @param imageView
   */
  @Override
  public void displayImageInResource(Context context, int resId, ImageView imageView) {
      GlideApp.with(context).load(resId).diskCacheStrategy(DiskCacheStrategy.NONE).into(imageView);
  }

  @Override
  public void displayImageInResource(Fragment fragment, int resId, ImageView imageView) {
      GlideApp.with(fragment).load(resId).diskCacheStrategy(DiskCacheStrategy.NONE).into(imageView);
  }

  public void displayImageInResource(Activity fragment, int resId, ImageView imageView) {
      GlideApp.with(fragment).load(resId).diskCacheStrategy(DiskCacheStrategy.NONE).into(imageView);
  }

  /**
   *
   * @param fragment
   * @param resId
   * @param imageView
   * @param transformation 需要變換那種影象
   * @param errorResId
   */
  @Override
  public void displayImageInResourceTransform(Activity fragment, int resId, ImageView imageView,Transformation transformation,int errorResId) {
      GlideApp.with(fragment).load(resId).diskCacheStrategy(DiskCacheStrategy.NONE).apply(requestOptionsTransform(errorResId,errorResId,transformation)).into(imageView);
  }

  @Override
  public void displayImageInResourceTransform(Context context, int resId, ImageView imageView, Transformation transformation, int errorResId) {
      GlideApp.with(context).load(resId).diskCacheStrategy(DiskCacheStrategy.NONE).apply(requestOptionsTransform(errorResId,errorResId,transformation)).into(imageView);
  }

  @Override
  public void displayImageInResourceTransform(Fragment fragment, int resId, ImageView imageView, Transformation transformation, int errorResId) {
      GlideApp.with(fragment).load(resId).diskCacheStrategy(DiskCacheStrategy.NONE).apply(requestOptionsTransform(errorResId,errorResId,transformation)).into(imageView);
  }

  @Override
  public void displayImageByNet(Context context, String url, ImageView imageView, int defRes, Transformation transformation) {
      GlideApp.with(context).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).apply(requestOptionsTransform(defRes,defRes,transformation)).into(imageView);
  }

  @Override
  public void displayImageByNet(Fragment fragment, String url, ImageView imageView, int defRes, Transformation transformation) {
      GlideApp.with(fragment).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).apply(requestOptionsTransform(defRes,defRes,transformation)).into(imageView);
  }

  @Override
  public void displayImageByNet(Activity activity, String url, ImageView imageView, int defRes, Transformation transformation) {
      GlideApp.with(activity).load(url).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).apply(requestOptionsTransform(defRes,defRes,transformation)).into(imageView);
  }

  @Override
  public void clear(Activity activity, ImageView imageView) {
      GlideApp.with(activity).clear(imageView);
  }

  @Override
  public void clear(Context context, ImageView imageView) {
      GlideApp.with(context).clear(imageView);
  }

  @Override
  public void clear(Fragment fragment, ImageView imageView) {
      GlideApp.with(fragment).clear(imageView);
  }
//    預設的策略是DiskCacheStrategy.AUTOMATIC
//    DiskCacheStrategy.ALL 使用DATA和RESOURCE快取遠端資料,僅使用RESOURCE來快取本地資料。
//    DiskCacheStrategy.NONE 不使用磁碟快取
//    DiskCacheStrategy.DATA 在資源解碼前就將原始資料寫入磁碟快取
//    DiskCacheStrategy.RESOURCE 在資源解碼後將資料寫入磁碟快取,即經過縮放等轉換後的圖片資源。
//    DiskCacheStrategy.AUTOMATIC 根據原始圖片資料和資源編碼策略來自動選擇磁碟快取策略。
  @Override
  public void displayImageByDiskCacheStrategy(Fragment fragment, String url, DiskCacheStrategy diskCacheStrategy,ImageView imageView) {
      GlideApp.with(fragment).load(url).diskCacheStrategy(diskCacheStrategy).into(imageView);
  }
//    DiskCacheStrategy.NONE: 表示不快取任何內容。
//    DiskCacheStrategy.DATA: 表示只快取原始圖片。
//    DiskCacheStrategy.RESOURCE: 表示只快取轉換過後的圖片。
//    DiskCacheStrategy.ALL : 表示既快取原始圖片,也快取轉換過後的圖片。
//    DiskCacheStrategy.AUTOMATIC: 表示讓Glide根據圖片資源智慧地選擇使用哪一種快取策略(預設選項)。
  @Override
  public void displayImageByDiskCacheStrategy(Activity activity, String url, DiskCacheStrategy diskCacheStrategy,ImageView imageView) {
      GlideApp.with(activity).load(url).diskCacheStrategy(diskCacheStrategy).into(imageView);
  }

  @Override
  public void displayImageByDiskCacheStrategy(Context context, String url, DiskCacheStrategy diskCacheStrategy,ImageView imageView) {
      GlideApp.with(context).load(url).diskCacheStrategy(diskCacheStrategy).into(imageView);
  }

  @Override
  public void disPlayImageOnlyRetrieveFromCache(Fragment fragment, String url, ImageView imageView) {
      GlideApp.with(fragment)
              .load(url)
              .onlyRetrieveFromCache(true)
              .into(imageView);
  }

  @Override
  public void disPlayImageOnlyRetrieveFromCache(Activity activity, String url, ImageView imageView) {
      GlideApp.with(activity)
              .load(url)
              .onlyRetrieveFromCache(true)
              .into(imageView);
  }

  @Override
  public void disPlayImageOnlyRetrieveFromCache(Context context, String url, ImageView imageView) {
      GlideApp.with(context)
              .load(url)
              .onlyRetrieveFromCache(true)
              .into(imageView);
  }
  /**
   *如果你想確保一個特定的請求跳過磁碟和/或記憶體快取(比如,圖片驗證碼 –)
   * @param fragment
   * @param url
   * @param imageView
   * @param skipflag  是否跳過記憶體快取
   * @param diskCacheStratey  是否跳過磁碟快取
   */
  @Override
  public void disPlayImageSkipMemoryCache(Fragment fragment, String url, ImageView imageView, boolean skipflag, boolean diskCacheStratey) {
      GlideApp.with(fragment)
              .load(url)
              .diskCacheStrategy(diskCacheStratey?DiskCacheStrategy.NONE:DiskCacheStrategy.AUTOMATIC)
              .skipMemoryCache(skipflag)
              .into(imageView);
  }

  @Override
  public void disPlayImageSkipMemoryCache(Activity activity, String url, ImageView imageView, boolean skipflag, boolean diskCacheStratey) {
      GlideApp.with(activity)
              .load(url)
              .diskCacheStrategy(diskCacheStratey?DiskCacheStrategy.NONE:DiskCacheStrategy.AUTOMATIC)
              .skipMemoryCache(skipflag)
              .into(imageView);
  }

  @Override
  public void disPlayImageSkipMemoryCache(Context context, String url, ImageView imageView, boolean skipflag, boolean diskCacheStratey) {
      GlideApp.with(context)
              .load(url)
              .diskCacheStrategy(diskCacheStratey?DiskCacheStrategy.NONE:DiskCacheStrategy.AUTOMATIC)
              .skipMemoryCache(skipflag)
              .into(imageView);
  }

  @Override
  public void disPlayImageErrorReload(Fragment fragment, String url, String fallbackUrl, ImageView imageView) {
      GlideApp.with(fragment)
              .load(url)
              .error(GlideApp.with(fragment)
                      .load(fallbackUrl))
              .into(imageView);
  }

  @Override
  public void disPlayImageErrorReload(Activity activity, String url, String fallbackUrl, ImageView imageView) {
      GlideApp.with(activity)
              .load(url)
              .error(GlideApp.with(activity)
                      .load(fallbackUrl))
              .into(imageView);
  }

  @Override
  public void disPlayImageErrorReload(Context context, String url, String fallbackUrl, ImageView imageView) {
      GlideApp.with(context)
              .load(url)
              .error(GlideApp.with(context)
                      .load(fallbackUrl))
              .into(imageView);
  }

  @Override
  public void disPlayImagedisallowHardwareConfig(Fragment fragment, String url, ImageView imageView) {
      GlideApp.with(fragment)
              .load(url)
              .disallowHardwareConfig()
              .into(imageView);
      //第二種方法
//        RequestOptions options = new RequestOptions().disallowHardwareConfig();
//        Glide.with(fragment)
//                .load(url)
//                .apply(options)
//                .into(imageView);
  }

  @Override
  public void disPlayImagedisallowHardwareConfig(Activity activity, String url, ImageView imageView) {
      GlideApp.with(activity)
              .load(url)
              .disallowHardwareConfig()
              .into(imageView);
  }

  @Override
  public void disPlayImagedisallowHardwareConfig(Context context, String url, ImageView imageView) {
      GlideApp.with(context)
              .load(url)
              .disallowHardwareConfig()
              .into(imageView);
  }
  //監聽進度
  @Override
  public void disPlayImageProgress(Context context, final String url, ImageView imageView, int placeholderResId, int errorResId, OnGlideImageViewListener listener) {
      GlideApp.with(context)
              .load(url)
              .diskCacheStrategy(DiskCacheStrategy.NONE)//todo 我是為了測試,看到進度條,才把快取策略設定成這樣的,專案中一定不要這樣做
              .apply(new RequestOptions()
                      .placeholder(placeholderResId)
                      .error(errorResId))
              .listener(new RequestListener<Drawable>() {
                  @Override
                  public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                      mainThreadCallback(url,mLastBytesRead, mTotalBytes, true, e);
                      ProgressManager.removeProgressListener(internalProgressListener);
                      return false;
                  }
                  @Override
                  public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                      mainThreadCallback(url,mLastBytesRead, mTotalBytes, true, null);
                      ProgressManager.removeProgressListener(internalProgressListener);
                      return false;
                  }
              }).into(imageView);

      //賦值 上去
      onGlideImageViewListener=listener;
      mMainThreadHandler = new Handler(Looper.getMainLooper());
      internalProgressListener = new OnProgressListener() {
          @Override
          public void onProgress(String imageUrl, final long bytesRead, final long totalBytes, final boolean isDone, final GlideException exception) {
              if (totalBytes == 0) return;
              if (mLastBytesRead == bytesRead && mLastStatus == isDone) return;

              mLastBytesRead = bytesRead;
              mTotalBytes = totalBytes;
              mLastStatus = isDone;
              mainThreadCallback(imageUrl,bytesRead, totalBytes, isDone, exception);

              if (isDone) {
                  ProgressManager.removeProgressListener(this);
              }
          }
      };
      ProgressManager.addProgressListener(internalProgressListener);



  }

  @Override
  public void disPlayImageProgress(Activity activity, final String url, ImageView imageView, int placeholderResId, int errorResId, OnGlideImageViewListener listener) {
      GlideApp.with(activity)
              .load(url)
              .diskCacheStrategy(DiskCacheStrategy.NONE)//todo 我是為了測試,看到進度條,才把快取策略設定成這樣的,專案中一定不要這樣做
              .apply(new RequestOptions()
                      .placeholder(placeholderResId)
                      .error(errorResId))
              .listener(new RequestListener<Drawable>() {
                  @Override
                  public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                      mainThreadCallback(url,mLastBytesRead, mTotalBytes, true, e);
                      ProgressManager.removeProgressListener(internalProgressListener);
                      return false;
                  }
                  @Override
                  public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                      mainThreadCallback(url,mLastBytesRead, mTotalBytes, true, null);
                      ProgressManager.removeProgressListener(internalProgressListener);
                      return false;
                  }
              }).into(imageView);

      //賦值 上去
      onGlideImageViewListener=listener;
      mMainThreadHandler = new Handler(Looper.getMainLooper());
      internalProgressListener = new OnProgressListener() {
          @Override
          public void onProgress(String imageUrl, final long bytesRead, final long totalBytes, final boolean isDone, final GlideException exception) {
              if (totalBytes == 0) return;
              if (mLastBytesRead == bytesRead && mLastStatus == isDone) return;

              mLastBytesRead = bytesRead;
              mTotalBytes = totalBytes;
              mLastStatus = isDone;
              mainThreadCallback(imageUrl,bytesRead, totalBytes, isDone, exception);

              if (isDone) {
                  ProgressManager.removeProgressListener(this);
              }
          }
      };
      ProgressManager.addProgressListener(internalProgressListener);
  }

  @Override
  public void disPlayImageProgress(Fragment fragment, final String url, ImageView imageView, int placeholderResId, int errorResId, OnGlideImageViewListener listener) {
      GlideApp.with(fragment)
              .load(url)
              .diskCacheStrategy(DiskCacheStrategy.NONE)//todo 我是為了測試,看到進度條,才把快取策略設定成這樣的,專案中一定不要這樣做
              .apply(new RequestOptions()
                      .placeholder(placeholderResId)
                      .error(errorResId))
              .listener(new RequestListener<Drawable>() {
                  @Override
                  public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                      mainThreadCallback(url,mLastBytesRead, mTotalBytes, true, e);
                      ProgressManager.removeProgressListener(internalProgressListener);
                      return false;
                  }
                  @Override
                  public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                      mainThreadCallback(url,mLastBytesRead, mTotalBytes, true, null);
                      ProgressManager.removeProgressListener(internalProgressListener);
                      return false;
                  }
              }).into(imageView);

      //賦值 上去
      onGlideImageViewListener=listener;
      mMainThreadHandler = new Handler(Looper.getMainLooper());
      internalProgressListener = new OnProgressListener() {
          @Override
          public void onProgress(String imageUrl, final long bytesRead, final long totalBytes, final boolean isDone, final GlideException exception) {
              if (totalBytes == 0) return;
              if (mLastBytesRead == bytesRead && mLastStatus == isDone) return;

              mLastBytesRead = bytesRead;
              mTotalBytes = totalBytes;
              mLastStatus = isDone;
              mainThreadCallback(imageUrl,bytesRead, totalBytes, isDone, exception);

              if (isDone) {
                  ProgressManager.removeProgressListener(this);
              }
          }
      };
      ProgressManager.addProgressListener(internalProgressListener);
  }



  @Override
  public void disPlayImageProgressByOnProgressListener(Context context, final String url, ImageView imageView, int placeholderResId, int errorResId, OnProgressListener onProgressListener) {
      GlideApp.with(context)
              .load(url)
              .diskCacheStrategy(DiskCacheStrategy.NONE)//todo 我是為了測試,看到進度條,才把快取策略設定成這樣的,專案中一定不要這樣做
              .apply(new RequestOptions()
                      .placeholder(placeholderResId)
                      .error(errorResId))
              .listener(new RequestListener<Drawable>() {
                  @Override
                  public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                      mainThreadCallback(url,mLastBytesRead, mTotalBytes, true, e);
                      ProgressManager.removeProgressListener(internalProgressListener);
                      return false;
                  }
                  @Override
                  public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                      mainThreadCallback(url,mLastBytesRead, mTotalBytes, true, null);
                      ProgressManager.removeProgressListener(internalProgressListener);
                      return false;
                  }
              }).into(imageView);

      //賦值 上去
      this.onProgressListener = onProgressListener;
      mMainThreadHandler = new Handler(Looper.getMainLooper());
      internalProgressListener = new OnProgressListener() {
          @Override
          public void onProgress(String imageUrl, final long bytesRead, final long totalBytes, final boolean isDone, final GlideException exception) {
              if (totalBytes == 0) return;
              if (mLastBytesRead == bytesRead && mLastStatus == isDone) return;

              mLastBytesRead = bytesRead;
              mTotalBytes = totalBytes;
              mLastStatus = isDone;
              mainThreadCallback(imageUrl,bytesRead, totalBytes, isDone, exception);

              if (isDone) {
                  ProgressManager.removeProgressListener(this);
              }
          }
      };
      ProgressManager.addProgressListener(internalProgressListener);
  }

  @Override
  public void disPlayImageProgressByOnProgressListener(Activity activity, final String url, ImageView imageView, int placeholderResId, int errorResId, OnProgressListener onProgressListener) {
      GlideApp.with(activity)
              .load(url)
              .diskCacheStrategy(DiskCacheStrategy.NONE)//todo 我是為了測試,看到進度條,才把快取策略設定成這樣的,專案中一定不要這樣做
              .apply(new RequestOptions()
                      .placeholder(placeholderResId)
                      .error(errorResId))
              .listener(new RequestListener<Drawable>() {
                  @Override
                  public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                      mainThreadCallback(url,mLastBytesRead, mTotalBytes, true, e);
                      ProgressManager.removeProgressListener(internalProgressListener);
                      return false;
                  }
                  @Override
                  public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                      mainThreadCallback(url,mLastBytesRead, mTotalBytes, true, null);
                      ProgressManager.removeProgressListener(internalProgressListener);
                      return false;
                  }
              }).into(imageView);

      //賦值 上去
      this.onProgressListener = onProgressListener;
      mMainThreadHandler = new Handler(Looper.getMainLooper());
      internalProgressListener = new OnProgressListener() {
          @Override
          public void onProgress(String imageUrl, final long bytesRead, final long totalBytes, final boolean isDone, final GlideException exception) {
              if (totalBytes == 0) return;
              if (mLastBytesRead == bytesRead && mLastStatus == isDone) return;

              mLastBytesRead = bytesRead;
              mTotalBytes = totalBytes;
              mLastStatus = isDone;
              mainThreadCallback(imageUrl,bytesRead, totalBytes, isDone, exception);

              if (isDone) {
                  ProgressManager.removeProgressListener(this);
              }
          }
      };
      ProgressManager.addProgressListener(internalProgressListener);
  }

  @Override
  public void disPlayImageProgressByOnProgressListener(Fragment fragment, final String url, ImageView imageView, int placeholderResId, int errorResId, OnProgressListener onProgressListener) {
      GlideApp.with(fragment)
              .load(url)
              .diskCacheStrategy(DiskCacheStrategy.NONE)//todo 我是為了測試,看到進度條,才把快取策略設定成這樣的,專案中一定不要這樣做
              .apply(new RequestOptions()
                      .placeholder(placeholderResId)
                      .error(errorResId))
              .listener(new RequestListener<Drawable>() {
                  @Override
                  public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                      mainThreadCallback(url,mLastBytesRead, mTotalBytes, true, e);
                      ProgressManager.removeProgressListener(internalProgressListener);
                      return false;
                  }
                  @Override
                  public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                      mainThreadCallback(url,mLastBytesRead, mTotalBytes, true, null);
                      ProgressManager.removeProgressListener(internalProgressListener);
                      return false;
                  }
              }).into(imageView);

      //賦值 上去
      this.onProgressListener = onProgressListener;
      mMainThreadHandler = new Handler(Looper.getMainLooper());
      internalProgressListener = new OnProgressListener() {
          @Override
          public void onProgress(String imageUrl, final long bytesRead, final long totalBytes, final boolean isDone, final GlideException exception) {
              if (totalBytes == 0) return;
              if (mLastBytesRead == bytesRead && mLastStatus == isDone) return;

              mLastBytesRead = bytesRead;
              mTotalBytes = totalBytes;
              mLastStatus = isDone;
              mainThreadCallback(imageUrl,bytesRead, totalBytes, isDone, exception);

              if (isDone) {
                  ProgressManager.removeProgressListener(this);
              }
          }
      };
      ProgressManager.addProgressListener(internalProgressListener);
  }

  @Override
  public void displayImageByTransition(Context context, String url, TransitionOptions transitionOptions, ImageView imageView) {

      if (transitionOptions instanceof DrawableTransitionOptions){
          GlideApp.with(context)
                  .load(url)
                  .transition((DrawableTransitionOptions)transitionOptions)
                  .into(imageView);
      }else {
          GlideApp.with(context)
                  .asBitmap()
                  .load(url)
                  .transition(transitionOptions)
                  .into(imageView);
      }

  }

  @Override
  public void displayImageByTransition(Activity activity, String url, TransitionOptions transitionOptions, ImageView imageView) {
      if (transitionOptions instanceof DrawableTransitionOptions){
          GlideApp.with(activity)
                  .load(url)
                  .transition((DrawableTransitionOptions)transitionOptions)
                  .into(imageView);
      }else {
          GlideApp.with(activity)
                  .asBitmap()
                  .load(url)
                  .transition(transitionOptions)
                  .into(imageView);
      }
  }

  @Override
  public void displayImageByTransition(Fragment fragment, String url, TransitionOptions transitionOptions, ImageView imageView) {
      if (transitionOptions instanceof DrawableTransitionOptions){
          GlideApp.with(fragment)
                  .load(url)
                  .transition((DrawableTransitionOptions)transitionOptions)
                  .into(imageView);
      }else {
          GlideApp.with(fragment)
                  .asBitmap()
                  .load(url)
                  .transition(transitionOptions)
                  .into(imageView);
      }
  }

  @Override
  public void glidePauseRequests(Context context) {
      GlideApp.with(context).pauseRequests();
  }

  @Override
  public void glidePauseRequests(Activity activity) {
      GlideApp.with(activity).pauseRequests();
  }

  @Override
  public void glidePauseRequests(Fragment fragment) {
      GlideApp.with(fragment).pauseRequests();
  }

  @Override
  public void glideResumeRequests(Context context) {
      GlideApp.with(context).resumeRequests();
  }

  @Override
  public void glideResumeRequests(Activity activity) {
      GlideApp.with(activity).resumeRequests();
  }

  @Override
  public void glideResumeRequests(Fragment fragment) {
      GlideApp.with(fragment).resumeRequests();
  }

  /**
   *
   *  載入縮圖
   * @param context
   * @param url 圖片url
   * @param backUrl 縮圖的url
   * @param thumbnailSize 如果需要放大放小的數值
   * @param imageView
   */
  @Override
  public void displayImageThumbnail(Context context, String url, String backUrl, int thumbnailSize, ImageView imageView) {

      if(thumbnailSize == 0) {
          GlideApp.with(context)
                  .load(url)
                  .thumbnail(Glide.with(context)
                          .load(backUrl))
                  .into(imageView);
      }else {

          //越小,圖片越小,低網路的情況,圖片越小
          GlideApp.with(context)
                  .load(url)
                  .diskCacheStrategy(DiskCacheStrategy.NONE)//為了測試不快取
                  .thumbnail(GlideApp.with(context)
                          .load(backUrl)
                          .override(thumbnailSize))// API 來強制 Glide 在縮圖請求中載入一個低解析度影象
                  .into(imageView);
      }

  }

  @Override
  public void displayImageThumbnail(Activity activity, String url, String backUrl, int thumbnailSize, ImageView imageView) {
      if(thumbnailSize == 0) {
          GlideApp.with(activity)
                  .load(url)
                  .thumbnail(Glide.with(activity)
                          .load(backUrl))
                  .into(imageView);
      }else {

          //越小,圖片越小,低網路的情況,圖片越小
          GlideApp.with(activity)
                  .load(url)
                  .diskCacheStrategy(DiskCacheStrategy.NONE)//為了測試不快取
                  .thumbnail(GlideApp.with(activity)
                          .load(backUrl)
                          .override(thumbnailSize))// API 來強制 Glide 在縮圖請求中載入一個低解析度影象
                  .into(imageView);
      }
  }

  @Override
  public void displayImageThumbnail(Fragment fragment, String url, String backUrl, int thumbnailSize, ImageView imageView) {
      if(thumbnailSize == 0) {
          GlideApp.with(fragment)
                  .load(url)
                  .thumbnail(Glide.with(fragment)
                          .load(backUrl))
                  .into(imageView);
      }else {

          //越小,圖片越小,低網路的情況,圖片越小
          GlideApp.with(fragment)
                  .load(url)
                  .diskCacheStrategy(DiskCacheStrategy.NONE)//為了測試不快取
                  .thumbnail(GlideApp.with(fragment)
                          .load(backUrl)
                          .override(thumbnailSize))// API 來強制 Glide 在縮圖請求中載入一個低解析度影象
                  .into(imageView);
      }
  }

  /**
   *  * thumbnail 方法有一個簡化版本,它只需要一個 sizeMultiplier 引數。
   * 如果你只是想為你的載入相同的圖片,但尺寸為 View 或 Target 的某個百分比的話特別有用:
   * @param fragment
   * @param url
   * @param thumbnailSize
   * @param imageView
   */
  @Override
  public void displayImageThumbnail(Fragment fragment, String url, float thumbnailSize, ImageView imageView) {
      if(thumbnailSize >= 0.0F && thumbnailSize <= 1.0F) {
          GlideApp.with(fragment)
                  .load(url)
                  .thumbnail(/*sizeMultiplier=*/ thumbnailSize)
                  .into(imageView);
      } else {
          throw new IllegalArgumentException("thumbnailSize 的值必須在0到1之間");
      }

  }

  @Override
  public void displayImageThumbnail(Activity activity, String url, float thumbnailSize, ImageView imageView) {
      if(thumbnailSize >= 0.0F && thumbnailSize <= 1.0F) {
          GlideApp.with(activity)
                  .load(url)
                  .thumbnail(/*sizeMultiplier=*/ thumbnailSize)
                  .into(imageView);
      } else {
          throw new IllegalArgumentException("thumbnailSize 的值必須在0到1之間");
      }
  }

  @Override
  public void displayImageThumbnail(Context context, String url, float thumbnailSize, ImageView imageView) {
      if(thumbnailSize >= 0.0F && thumbnailSize <= 1.0F) {
          GlideApp.with(context)
                  .load(url)
                  .thumbnail(/*sizeMultiplier=*/ thumbnailSize)
                  .into(imageView);
      } else {
          throw new IllegalArgumentException("thumbnailSize 的值必須在0到1之間");
      }
  }

  private Handler mMainThreadHandler;
  private long mTotalBytes = 0;
  private long mLastBytesRead = 0;
  private void mainThreadCallback(final String url, final long bytesRead, final long totalBytes, final boolean isDone, final GlideException exception) {
      mMainThreadHandler.post(new Runnable() {
          @Override
          public void run() {
              // TODO: 2018/4/20 放慢效果  實際的專案中給我去掉
              SystemClock.sleep(100);
              final int percent = (int) ((bytesRead * 1.0f / totalBytes) * 100.0f);
              if (onProgressListener != null) {
                  onProgressListener.onProgress(url, bytesRead, totalBytes, isDone, exception);
              }

              if (onGlideImageViewListener != null) {
                  onGlideImageViewListener.onProgress(percent, isDone, exception);
              }
          }
      });
  }
  private boolean mLastStatus = false;
  private OnProgressListener internalProgressListener;
  private OnGlideImageViewListener onGlideImageViewListener;
  private OnProgressListener onProgressListener;

  /**
   * 指定傳入的那種圖片的變形
   * @param placeholderResId
   * @param errorResId
   * @param transformation
   * @return
   */
  public RequestOptions requestOptionsTransform(int placeholderResId, int errorResId,Transformation transformation) {
      return new RequestOptions()
              .placeholder(placeholderResId)
              .error(errorResId).transform(transformation);
  }
  /**
   * 載入資原始檔的同時,對圖片進行處理
   * @param context
   * @param resId
   * @param imageView
   * @param transformations
   */
  @Override
  public void displayImageInResource(Context context, int resId, ImageView imageView, BitmapTransformation transformations) {
      GlideApp.with(context).load(resId).diskCacheStrategy(DiskCacheStrategy.NONE).transform(transformations).into(imageView);
  }

  @Override
  public void displayImageInResource(Fragment fragment, int resId,  ImageView imageView, BitmapTransformation transformations) {
      GlideApp.with(fragment).load(resId).diskCacheStrategy(DiskCacheStrategy.NONE).transform(transformations).into(imageView);
  }

  /**
   * 當傳入到其他的東西的時候,我要保證圖片不變形
   * @param placeholderResId
   * @param errorResId
   * @param transformation
   * @return
   */
  public RequestOptions requestOptionsNoTransform(int placeholderResId, int errorResId, Transformation<Bitmap> transformation) {
      return new RequestOptions()
              .placeholder(placeholderResId)
              .error(errorResId).transform(transformation);
  }
  /**
   * 載入資原始檔失敗了,載入中的預設圖和失敗的圖片
   * @param context
   * @param resId
   * @param imageView
   * @param defRes
   */
  @Override
  public void displayImageInResource(Context context, int resId,  ImageView imageView, int defRes) {
      GlideApp.with(context).load(resId).diskCacheStrategy(DiskCacheStrategy.NONE).placeholder(defRes).error(defRes).into(imageView);
  }

  @Override
  public void displayImageInResource(Fragment fragment, int resId, ImageView imageView, int defRes) {
      GlideApp.with(fragment).load(resId).diskCacheStrategy(DiskCacheStrategy.NONE).placeholder(defRes).error(defRes).into(imageView);
  }
  //關心context
  @Override
  public void displayImageInResource(Context context, int resId,  ImageView imageView, int defRes, BitmapTransformation transformations) {
      GlideApp.with(context).load(resId).diskCacheStrategy(DiskCacheStrategy.NONE).placeholder(defRes).error(defRes).transform(transformations).into(imageView);
  }
  //關心fragment
  @Override
  public void displayImageInResource(Fragment fragment, int resId,  ImageView imageView, int defRes, BitmapTransformation transformations) {
      GlideApp.with(fragment).load(resId).diskCacheStrategy(DiskCacheStrategy.NONE).placeholder(defRes).error(defRes).transform(transformations).into(imageView);
  }


}

複製程式碼

ImageLoaderV4呼叫類

package code.shiming.com.imageloader471;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.support.v4.app.Fragment;
import android.widget.ImageView;

import com.bumptech.glide.TransitionOptions;
import com.bumptech.glide.load.Transformation;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;

import java.io.File;

import code.shiming.com.imageloader471.listener.IGetBitmapListener;
import code.shiming.com.imageloader471.listener.IGetDrawableListener;
import code.shiming.com.imageloader471.listener.IImageLoaderListener;
import code.shiming.com.imageloader471.listener.ImageSize;
import code.shiming.com.imageloader471.okhttp.OnGlideImageViewListener;
import code.shiming.com.imageloader471.okhttp.OnProgressListener;


/**
 * Created by shiming on 2016/10/26.
 */
public class ImageLoaderV4 implements IImageLoaderClient {
    /**
     * volatile 關鍵字:我個人理解的是:使用volatile關鍵字的程式在併發時能夠正確執行。
     * 但是它不能夠代替synchronized關鍵字。在網上找到這麼一句話:
     * 觀察加入volatile關鍵字和沒有加入volatile關鍵字時所生成的彙編程式碼發現,
     * 加入volatile關鍵字時,會多出一個lock字首指令lock字首指令實際上相當於一個記憶體屏障(也成記憶體柵欄),
     * 記憶體屏障會提供3個功能:1)它確保指令重排序時不會把其後面的指令排到記憶體屏障之前的位置,
     * 也不會把前面的指令排到記憶體屏障的後面;即在執行到記憶體屏障這句指令時,在它前面的操作已經全部完成;
     * 2)它會強制將對快取的修改操作立即寫入主存;3)如果是寫操作,它會導致其他CPU中對應的快取行無效。
     */
    private volatile static ImageLoaderV4 instance;
    private IImageLoaderClient client;

    private ImageLoaderV4() {
        client = new GlideImageLoaderClient();
    }

    /***
     * 設定 圖片載入庫客戶端
     */

    public void setImageLoaderClient(Context context, IImageLoaderClient client) {
        if (this.client != null) {
            this.client.clearMemoryCache(context);
        }

        if (this.client != client) {
            this.client = client;
            if (this.client != null) {
                this.client.init(context);
            }
        }

    }
    /**
     * 因為每次呼叫例項都需要判斷同步鎖,很多專案包括很多人都是用這種的
     * 雙重判斷校驗的方法,這種的方法看似很完美的解決了效率的問題,但是它
     * 在併發量不多,安全性不太高的情況下能完美的執行,但是,
     * 在jvm編譯的過程中會出現指令重排的優化過程,這就會導致singleton實際上
     * 沒有被初始化,就分配了記憶體空間,也就是說singleton!=null但是又沒有被初始化,
     * 這就會導致返回的singletonthird返回的是不完整的
     * 參考:http://www.360doc.com/content/11/0810/12/1542811_139352888.shtml
     * 建議使用內部類實現單利模式
     */
    public static ImageLoaderV4 getInstance() {
        if (instance == null) {
            synchronized (ImageLoaderV4.class) {
                if (instance == null) {
                    instance = new ImageLoaderV4();
                }
            }
        }
        return instance;
    }

    @Override
    public void init(Context context) {

    }

    @Override
    public void destroy(Context context) {
        if (client != null) {
            client.destroy(context);
            client = null;
        }

        instance = null;
    }

    @Override
    public File getCacheDir(Context context) {
        if (client != null) {
            return client.getCacheDir(context);
        }
        return null;
    }

    @Override
    public void clearMemoryCache(Context context) {
        if (client != null) {
            client.clearMemoryCache(context);
        }
    }

    @Override
    public void clearDiskCache(Context context) {
        if (client != null) {
            client.clearDiskCache(context);
        }
    }

    @Override
    public Bitmap getBitmapFromCache(Context context, String url) {
        if (client != null) {
            return client.getBitmapFromCache(context, url);
        }
        return null;
    }

    /**
     * 不是
     * @param context
     * @param url
     * @param listener
     */
    @Override
    public void getBitmapFromCache(Context context, String url, IGetBitmapListener listener) {
        if (client != null) {
            client.getBitmapFromCache(context, url, listener);
        }
    }

    @Override
    public void displayImage(Context context, int resId, ImageView imageView) {
        if (client != null) {
            client.displayImage(context, resId, imageView);
        }
    }

    @Override
    public void displayImage(Context context, String url, ImageView imageView) {
        if (client != null) {
            client.displayImage(context, url, imageView);
        }
    }

    @Override
    public void displayImage(Context context, String url, ImageView imageView, boolean isCache) {
        if (client != null) {
            client.displayImage(context, url, imageView,isCache);
        }
    }

    @Override
    public void displayImage(Fragment fragment, String url, ImageView imageView) {
        if (client != null) {
            client.displayImage(fragment, url, imageView);
        }
    }

    @Override
    public void displayImage(Context context, String url, ImageView imageView, int defRes) {
        if (client != null) {
            client.displayImage(context, url, imageView, defRes);
        }
    }

    @Override
    public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes) {
        if (client != null) {
            client.displayImage(fragment, url, imageView, defRes);
        }
    }

    @Override
    public void displayImage(Context context, String url, ImageView imageView, int defRes,BitmapTransformation transformations) {
        if (client != null) {
            client.displayImage(context, url, imageView, defRes, transformations);
        }
    }

    @Override
    public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes, BitmapTransformation transformations) {
        if (client != null) {
            client.displayImage(fragment, url, imageView, defRes, transformations);
        }
    }

    @Override
    public void displayImage(Context context, String url, ImageView imageView, int defRes, ImageSize size) {
        if (client != null) {
            client.displayImage(context, url, imageView, defRes, size);
        }
    }

    @Override
    public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes, ImageSize size) {
        if (client != null) {
            client.displayImage(fragment, url, imageView, defRes, size);
        }
    }

    @Override
    public void displayImage(Context context, String url, ImageView imageView, int defRes, boolean cacheInMemory) {
        if (client != null) {
            client.displayImage(context, url, imageView, defRes, cacheInMemory);
        }
    }

    @Override
    public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes, boolean cacheInMemory) {
        if (client != null) {
            client.displayImage(fragment, url, imageView, defRes, cacheInMemory);
        }
    }

    @Override
    public void displayImage(Context context, String url, ImageView imageView, IImageLoaderListener listener) {
        if (client != null) {
            client.displayImage(context, url, imageView, listener);
        }
    }

    @Override
    public void displayImage(Fragment fragment, String url, ImageView imageView, IImageLoaderListener listener) {
        if (client != null) {
            client.displayImage(fragment, url, imageView, listener);
        }
    }

    @Override
    public void displayImage(Context context, String url, ImageView imageView, int defRes, IImageLoaderListener listener) {
        if (client != null) {
            client.displayImage(context, url, imageView, defRes, listener);
        }
    }

    @Override
    public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes, IImageLoaderListener listener) {
        if (client != null) {
            client.displayImage(fragment, url, imageView, defRes, listener);
        }
    }

    @Override
    public void displayCircleImage(Context context, String url, ImageView imageView, int defRes) {
        if (client != null) {
            client.displayCircleImage(context, url, imageView, defRes);
        }
    }

    @Override
    public void displayCircleImage(Fragment fragment, String url, ImageView imageView, int defRes) {
        if (client != null) {
            client.displayCircleImage(fragment, url, imageView, defRes);
        }
    }

    @Override
    public void displayRoundImage(Context context, String url, ImageView imageView, int defRes, int radius) {
        if (client != null) {
            client.displayRoundImage(context, url, imageView, defRes, radius);
        }
    }

    @Override
    public void displayBlurImage(Context context, String url, int blurRadius, final IGetDrawableListener listener) {
        if (client != null) {
            client.displayBlurImage(context, url, blurRadius, listener);
        }
    }

    @Override
    public void displayRoundImage(Fragment fragment, String url, ImageView imageView, int defRes, int radius) {
        if (client != null) {
            client.displayRoundImage(fragment, url, imageView, defRes, radius);
        }
    }

    @Override
    public void displayBlurImage(Context context, String url, ImageView imageView, int defRes, int blurRadius) {
        if (client != null) {
            client.displayBlurImage(context, url, imageView, defRes, blurRadius);
        }
    }

    @Override
    public void displayBlurImage(Context context, int resId, ImageView imageView, int blurRadius) {
        if (client != null) {
            client.displayBlurImage(context, resId, imageView, blurRadius);
        }
    }

    @Override
    public void displayBlurImage(Fragment fragment, String url, ImageView imageView, int defRes, int blurRadius) {
        if (client != null) {
            client.displayBlurImage(fragment, url, imageView, defRes, blurRadius);
        }
    }

    @Override
    public void displayImageInResource(Context context, int resId,  ImageView imageView) {
        if (client != null) {
            client.displayImageInResource(context, resId,  imageView);
        }
    }

    @Override
    public void displayImageInResource(Fragment fragment, int resId,  ImageView imageView) {
        if (client != null) {
            client.displayImageInResource(fragment, resId,  imageView);
        }
    }

    @Override
    public void displayImageInResource(Context context, int resId, ImageView imageView, BitmapTransformation transformations) {
        if (client != null) {
            client.displayImageInResource(context, resId, imageView, transformations);
        }
    }

    @Override
    public void displayImageInResource(Fragment fragment, int resId,  ImageView imageView, BitmapTransformation transformations) {
        if (client != null) {
            client.displayImageInResource(fragment, resId, imageView, transformations);
        }
    }

    @Override
    public void displayImageInResource(Context context, int resId,  ImageView imageView, int defRes) {
        if (client != null) {
            client.displayImageInResource(context, resId, imageView, defRes);
        }
    }

    @Override
    public void displayImageInResource(Fragment fragment, int resId,  ImageView imageView, int defRes) {
        if (client != null) {
            client.displayImageInResource(fragment, resId, imageView, defRes);
        }
    }

    @Override
    public void displayImageInResource(Context context, int resId,  ImageView imageView, int defRes, BitmapTransformation transformations) {
        if (client != null) {
            client.displayImageInResource(context, resId, imageView, defRes, transformations);
        }
    }

    @Override
    public void displayImageInResource(Fragment fragment, int resId,  ImageView imageView, int defRes, BitmapTransformation transformations) {
        if (client != null) {
            client.displayImageInResource(fragment, resId,  imageView, defRes, transformations);
        }
    }

    @Override
    public void displayImageInResourceTransform(Activity activity, int resId, ImageView imageView, Transformation transformation, int errorResId) {
        if (client != null) {
            client.displayImageInResourceTransform(activity, resId,  imageView, transformation, errorResId);
        }
    }

    @Override
    public void displayImageInResourceTransform(Context context, int resId, ImageView imageView, Transformation transformation, int errorResId) {
        if (client != null) {
            client.displayImageInResourceTransform(context, resId,  imageView, transformation, errorResId);
        }
    }

    @Override
    public void displayImageInResourceTransform(Fragment fragment, int resId, ImageView imageView, Transformation transformation, int errorResId) {
        if (client != null) {
            client.displayImageInResourceTransform(fragment, resId,  imageView, transformation, errorResId);
        }
    }

    @Override
    public void displayImageByNet(Context context, String url, ImageView imageView, int defRes, Transformation transformation) {
        if (client != null) {
            client.displayImageByNet(context, url,  imageView, defRes, transformation);
        }
    }

    @Override
    public void displayImageByNet(Fragment fragment, String url, ImageView imageView, int defRes, Transformation transformation) {
        if (client != null) {
            client.displayImageByNet(fragment, url,  imageView, defRes, transformation);
        }
    }

    @Override
    public void displayImageByNet(Activity activity, String url, ImageView imageView, int defRes, Transformation transformation) {
        if (client != null) {
            client.displayImageByNet(activity, url,  imageView, defRes, transformation);
        }
    }
    /**儘管及時取消不必要的載入是很好的實踐,但這並不是必須的操作。
     * 實際上,當 Glide.with() 中傳入的 Activity 或 Fragment 例項銷燬時,
     * Glide 會自動取消載入並回收資源。這裡我隱藏了api的呼叫
     * {@hide}
     */
    @Override
    public void clear(Activity activity, ImageView imageView) {
        if (client != null) {
            client.clear(activity, imageView);
        }
    }
    /**儘管及時取消不必要的載入是很好的實踐,但這並不是必須的操作。
     * 實際上,當 Glide.with() 中傳入的 Activity 或 Fragment 例項銷燬時,
     * Glide 會自動取消載入並回收資源。這裡我隱藏了api的呼叫
     * {@hide}
     */
    @Override
    public void clear(Context context, ImageView imageView) {
        if (client != null) {
            client.clear(context, imageView);
        }
    }
    /**儘管及時取消不必要的載入是很好的實踐,但這並不是必須的操作。
     * 實際上,當 Glide.with() 中傳入的 Activity 或 Fragment 例項銷燬時,
     * Glide 會自動取消載入並回收資源。這裡我隱藏了api的呼叫
     * {@hide}
     */
    @Override
    public void clear(Fragment fragment, ImageView imageView) {
        if (client != null) {
            client.clear(fragment, imageView);
        }
    }

    /**
     * 指定選擇哪種快取的策略
     * @param fragment
     * @param url
     * @param diskCacheStrategy
     * @param imageView
     */
    @Override
    public void displayImageByDiskCacheStrategy(Fragment fragment, String url, DiskCacheStrategy diskCacheStrategy, ImageView imageView) {
        if (client != null) {
            client.displayImageByDiskCacheStrategy(fragment, url,  diskCacheStrategy, imageView);
        }
    }

    @Override
    public void displayImageByDiskCacheStrategy(Activity activity, String url, DiskCacheStrategy diskCacheStrategy, ImageView imageView) {
        if (client != null) {
            client.displayImageByDiskCacheStrategy(activity, url,  diskCacheStrategy, imageView);
        }
    }

    @Override
    public void displayImageByDiskCacheStrategy(Context context, String url, DiskCacheStrategy diskCacheStrategy, ImageView imageView) {
        if (client != null) {
            client.displayImageByDiskCacheStrategy(context, url,  diskCacheStrategy, imageView);
        }
    }

    @Override
    public void disPlayImageOnlyRetrieveFromCache(Fragment fragment, String url, ImageView imageView) {
        if (client != null) {
            client.disPlayImageOnlyRetrieveFromCache(fragment, url, imageView);
        }
    }

    @Override
    public void disPlayImageOnlyRetrieveFromCache(Activity activity, String url, ImageView imageView) {
        if (client != null) {
            client.disPlayImageOnlyRetrieveFromCache(activity, url, imageView);
        }
    }

    @Override
    public void disPlayImageOnlyRetrieveFromCache(Context context, String url, ImageView imageView) {
        if (client != null) {
            client.disPlayImageOnlyRetrieveFromCache(context, url, imageView);
        }
    }

    @Override
    public void disPlayImageSkipMemoryCache(Fragment fragment, String url, ImageView imageView, boolean skipflag, boolean diskCacheStratey) {
        if (client != null) {
            client.disPlayImageSkipMemoryCache(fragment, url, imageView,skipflag,diskCacheStratey);
        }
    }

    @Override
    public void disPlayImageSkipMemoryCache(Activity activity, String url, ImageView imageView, boolean skipflag, boolean diskCacheStratey) {
        if (client != null) {
            client.disPlayImageSkipMemoryCache(activity, url, imageView,skipflag,diskCacheStratey);
        }
    }

    @Override
    public void disPlayImageSkipMemoryCache(Context context, String url, ImageView imageView, boolean skipflag, boolean diskCacheStratey) {
        if (client != null) {
            client.disPlayImageSkipMemoryCache(context, url, imageView,skipflag,diskCacheStratey);
        }
    }

    @Override
    public void disPlayImageErrorReload(Fragment fragment, String url, String fallbackUrl, ImageView imageView) {
        if (client != null) {
            client.disPlayImageErrorReload(fragment, url,fallbackUrl, imageView);
        }
    }

    @Override
    public void disPlayImageErrorReload(Activity activity, String url, String fallbackUrl, ImageView imageView) {
        if (client != null) {
            client.disPlayImageErrorReload(activity, url,fallbackUrl, imageView);
        }
    }

    @Override
    public void disPlayImageErrorReload(Context context, String url, String fallbackUrl, ImageView imageView) {
        if (client != null) {
            client.disPlayImageErrorReload(context, url,fallbackUrl, imageView);
        }
    }

    @Override
    public void disPlayImagedisallowHardwareConfig(Fragment fragment, String url, ImageView imageView) {
        if (client != null) {
            client.disPlayImagedisallowHardwareConfig(fragment, url,imageView);
        }
    }

    @Override
    public void disPlayImagedisallowHardwareConfig(Activity activity, String url, ImageView imageView) {
        if (client != null) {
            client.disPlayImagedisallowHardwareConfig(activity, url,imageView);
        }
    }

    @Override
    public void disPlayImagedisallowHardwareConfig(Context context, String url, ImageView imageView) {
        if (client != null) {
            client.disPlayImagedisallowHardwareConfig(context, url,imageView);
        }
    }

    @Override
    public void disPlayImageProgress(Context context, String url, ImageView imageView, int placeholderResId, int errorResId, OnGlideImageViewListener listener) {
        if (client != null) {
            client.disPlayImageProgress(context, url,imageView,placeholderResId,errorResId,listener);
        }
    }

    @Override
    public void disPlayImageProgress(Activity activity, String url, ImageView imageView, int placeholderResId, int errorResId, OnGlideImageViewListener listener) {
        if (client != null) {
            client.disPlayImageProgress(activity, url,imageView,placeholderResId,errorResId,listener);
        }
    }

    @Override
    public void disPlayImageProgress(Fragment fragment, String url, ImageView imageView, int placeholderResId, int errorResId, OnGlideImageViewListener listener) {
        if (client != null) {
            client.disPlayImageProgress(fragment, url,imageView,placeholderResId,errorResId,listener);
        }
    }

    @Override
    public void disPlayImageProgressByOnProgressListener(Context context, String url, ImageView imageView, int placeholderResId, int errorResId, OnProgressListener onProgressListener) {
        if (client != null) {
            client.disPlayImageProgressByOnProgressListener(context, url,imageView,placeholderResId,errorResId,onProgressListener);
        }
    }

    @Override
    public void disPlayImageProgressByOnProgressListener(Activity activity, String url, ImageView imageView, int placeholderResId, int errorResId, OnProgressListener onProgressListener) {
        if (client != null) {
            client.disPlayImageProgressByOnProgressListener(activity, url,imageView,placeholderResId,errorResId,onProgressListener);
        }
    }

    /**
     * 需要監聽 總的位元組數,和檔案的大小,同時也可以擴充套件為,載入本地圖片
     * @param fragment
     * @param url
     * @param imageView
     * @param placeholderResId
     * @param errorResId
     * @param onProgressListener
     */
    @Override
    public void disPlayImageProgressByOnProgressListener(Fragment fragment, String url, ImageView imageView, int placeholderResId, int errorResId, OnProgressListener onProgressListener) {
        if (client != null) {
            client.disPlayImageProgressByOnProgressListener(fragment, url,imageView,placeholderResId,errorResId,onProgressListener);
        }
    }
    /**
     * 過渡選項
     TransitionOptions 用於決定你的載入完成時會發生什麼。
     使用 TransitionOption 可以應用以下變換:
     View淡入
     與佔位符交叉淡入
     或者什麼都不發生
     從白色 慢慢變透明 5s的間隔
     GlideApp.with(this)
     .load(ur11)
     .transition(withCrossFade(5000)) 可以傳入過度的時間
     .into(mImageView_7);
     */

    @Override
    public void displayImageByTransition(Context context, String url, TransitionOptions transitionOptions, ImageView imageView) {
        if (client != null) {
            client.displayImageByTransition(context, url,transitionOptions,imageView);
        }

    }

    @Override
    public void displayImageByTransition(Activity activity, String url, TransitionOptions transitionOptions, ImageView imageView) {
        if (client != null) {
            client.displayImageByTransition(activity, url,transitionOptions,imageView);
        }
    }

    @Override
    public void displayImageByTransition(Fragment fragment, String url, TransitionOptions transitionOptions, ImageView imageView) {
        if (client != null) {
            client.displayImageByTransition(fragment, url,transitionOptions,imageView);
        }
    }

    @Override
    public void glidePauseRequests(Context context) {
        if (client != null) {
            client.glidePauseRequests(context);
        }
    }

    @Override
    public void glidePauseRequests(Activity activity) {
        if (client != null) {
            client.glidePauseRequests(activity);
        }
    }

    @Override
    public void glidePauseRequests(Fragment fragment) {
        if (client != null) {
            client.glidePauseRequests(fragment);
        }
    }

    @Override
    public void glideResumeRequests(Context context) {
        if (client != null) {
            client.glideResumeRequests(context);
        }
    }

    @Override
    public void glideResumeRequests(Activity activity) {
        if (client != null) {
            client.glideResumeRequests(activity);
        }
    }

    @Override
    public void glideResumeRequests(Fragment fragment) {
        if (client != null) {
            client.glideResumeRequests(fragment);
        }
    }

    @Override
    public void displayImageThumbnail(Context context, String url, String backUrl, int thumbnailSize, ImageView imageView) {
        if (client != null) {
            client.displayImageThumbnail(context,url,backUrl,thumbnailSize,imageView);
        }
    }

    @Override
    public void displayImageThumbnail(Activity activity, String url, String backUrl, int thumbnailSize, ImageView imageView) {
        if (client != null) {
            client.displayImageThumbnail(activity,url,backUrl,thumbnailSize,imageView);
        }
    }

    @Override
    public void displayImageThumbnail(Fragment fragment, String url, String backUrl, int thumbnailSize, ImageView imageView) {
        if (client != null) {
            client.displayImageThumbnail(fragment,url,backUrl,thumbnailSize,imageView);
        }
    }

    /**
     * 沒有地址也需要指定縮圖
     * @param fragment
     * @param url
     * @param thumbnailSize
     * @param imageView
     */
    @Override
    public void displayImageThumbnail(Fragment fragment, String url, float thumbnailSize, ImageView imageView) {
        if (client != null) {
            client.displayImageThumbnail(fragment,url,thumbnailSize,imageView);
        }
    }

    @Override
    public void displayImageThumbnail(Activity activity, String url, float thumbnailSize, ImageView imageView) {
        if (client != null) {
            client.displayImageThumbnail(activity,url,thumbnailSize,imageView);
        }
    }

    @Override
    public void displayImageThumbnail(Context context, String url, float thumbnailSize, ImageView imageView) {
        if (client != null) {
            client.displayImageThumbnail(context,url,thumbnailSize,imageView);
        }
    }
}

複製程式碼

關於圖片下載進度的監聽,在AppGlideModuleProgress 需要初始化ProgressManager

@GlideModule
public class AppGlideModuleProgress extends AppGlideModule {
    /**
     OkHttp 是一個底層網路庫(相較於 Cronet 或 Volley 而言),儘管它也包含了 SPDY 的支援。
     OkHttp 與 Glide 一起使用可以提供可靠的效能,並且在載入圖片時通常比 Volley 產生的垃圾要少。
     對於那些想要使用比 Android 提供的 HttpUrlConnection 更 nice 的 API,
      或者想確保網路層程式碼不依賴於 app 安裝的裝置上 Android OS 版本的應用,OkHttp 是一個合理的選擇。
      如果你已經在 app 中某個地方使用了 OkHttp ,這也是選擇繼續為 Glide 使用 OkHttp 的一個很好的理由,就像選擇其他網路庫一樣。
     新增 OkHttp 整合庫的 Gradle 依賴將使 Glide 自動開始使用 OkHttp 來載入所有來自 http 和 https URL 的圖片
     * @param context
     * @param glide
     * @param registry
     */
    @Override
    public void registerComponents(Context context, Glide glide, Registry registry) {
        super.registerComponents(context, glide, registry);
        registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(ProgressManager.getOkHttpClient()));
    }
}
複製程式碼

ProgressManager

public class ProgressManager {

    private static List<WeakReference<OnProgressListener>> listeners = Collections.synchronizedList(new ArrayList<WeakReference<OnProgressListener>>());
    private static OkHttpClient okHttpClient;

    private ProgressManager() {
    }

    public static OkHttpClient getOkHttpClient() {
        if (okHttpClient == null) {
            okHttpClient = new OkHttpClient.Builder()
                    .addNetworkInterceptor(new Interceptor() {
                        @Override
                        public Response intercept(@NonNull Chain chain) throws IOException {
                            Request request = chain.request();
                            Response response = chain.proceed(request);
                            return response.newBuilder()
                                    .body(new ProgressResponseBody(request.url().toString(), response.body(), LISTENER))
                                    .build();
                        }
                    })
                    .build();
        }
        return okHttpClient;
    }

    private static final OnProgressListener LISTENER = new OnProgressListener() {
        @Override
        public void onProgress(String imageUrl, long bytesRead, long totalBytes, boolean isDone, GlideException exception) {
            if (listeners == null || listeners.size() == 0) return;

            for (int i = 0; i < listeners.size(); i++) {
                WeakReference<OnProgressListener> listener = listeners.get(i);
                OnProgressListener progressListener = listener.get();
                if (progressListener == null) {
                    listeners.remove(i);
                } else {
                    progressListener.onProgress(imageUrl, bytesRead, totalBytes, isDone, exception);
                }
            }
        }
    };

    public static void addProgressListener(OnProgressListener progressListener) {
        if (progressListener == null) return;

        if (findProgressListener(progressListener) == null) {
            listeners.add(new WeakReference<>(progressListener));
        }
    }

    public static void removeProgressListener(OnProgressListener progressListener) {
        if (progressListener == null) return;

        WeakReference<OnProgressListener> listener = findProgressListener(progressListener);
        if (listener != null) {
            listeners.remove(listener);
        }
    }

    private static WeakReference<OnProgressListener> findProgressListener(OnProgressListener listener) {
        if (listener == null) return null;
        if (listeners == null || listeners.size() == 0) return null;

        for (int i = 0; i < listeners.size(); i++) {
            WeakReference<OnProgressListener> progressListener = listeners.get(i);
            if (progressListener.get() == listener) {
                return progressListener;
            }
        }
        return null;
    }
}

複製程式碼

ProgressResponseBody

public class ProgressResponseBody extends ResponseBody {

    private String imageUrl;
    private ResponseBody responseBody;
    private OnProgressListener progressListener;
    private BufferedSource bufferedSource;

    public ProgressResponseBody(String url, ResponseBody responseBody, OnProgressListener progressListener) {
        this.imageUrl = url;
        this.responseBody = responseBody;
        this.progressListener = progressListener;
    }

    @Override
    public MediaType contentType() {
        return responseBody.contentType();
    }

    @Override
    public long contentLength() {
        return responseBody.contentLength();
    }

    @Override
    public BufferedSource source() {
        if (bufferedSource == null) {
            bufferedSource = Okio.buffer(source(responseBody.source()));
        }
        return bufferedSource;
    }

    private Source source(Source source) {
        return new ForwardingSource(source) {
            long totalBytesRead = 0;

            @Override
            public long read(@NonNull Buffer sink, long byteCount) throws IOException {
                long bytesRead = super.read(sink, byteCount);
                totalBytesRead += (bytesRead == -1) ? 0 : bytesRead;

                if (progressListener != null) {
                    progressListener.onProgress(imageUrl, totalBytesRead, contentLength(), (bytesRead == -1), null);
                }
                return bytesRead;
            }
        };
    }
}

複製程式碼

OnProgressListener

public interface OnProgressListener {
    /**
     * 
      * @param imageUrl 圖片地址
     * @param bytesRead 下載了多少位元組
     * @param totalBytes 總共的大小
     * @param isDone 是否完成
     * @param exception 異常
     */
    void onProgress(String imageUrl, long bytesRead, long totalBytes, boolean isDone, GlideException exception);
}

複製程式碼

OnGlideImageViewListener

public interface OnGlideImageViewListener {
    /**
     * 
     * @param percent 下載進度的百分比,不關心,大小
     * @param isDone 是否完成
     * @param exception 異常
     */
    void onProgress(int percent, boolean isDone, GlideException exception);
}
複製程式碼

glide4.X優點 1、新的文件,使用者可以通過提交請求到Glide’s gh-pages分支貢獻。 2、使用者可以新增新型別或自定義選項集來輕鬆地自定義Glide流暢的API。大量簡化個人請求型別,確保選項始終如一,易於使用,即使您正在載入不同型別的資源。 3、各種效能改進,包括在下載取樣影象時大量減少垃圾,更加智慧的預設磁碟快取策略,以及載入GIF時效能提升。 4、改進了檢視大小和佈局的處理,特別是在RecyclerView中。 官方文件:muyangmin.github.io/glide-docs-…

Glide V4變化較大的是庫處理選項的方式。在Glide v3中,選項是由一系列複雜的多型別構建器單獨處理的。在Glide v4中,這些已被具有單一型別的單個構建器和可以提供給構建器的一系列選項的物件所替代。Glide 生成的API通過將選項物件和任何包含的整合庫與構建器的選項合併,來建立單個流暢的API。 可以簡單理解為,Glide v4 將Glide V3中Glide.with()實現的一系列複雜功能拆分成一些獨立的API。

建議看官方文件,雖然需要點時間!

#####最後總結下Glide4.X對比Glide3.X的區別: ######1、選項(Options) Glide v4 中的一個比較大的改動是Glide庫處理選項(centerCrop()placeholder() 等)的方式。在 v3 版本中,選項由一系列複雜的異構建造者(multityped builders)單獨處理。在新版本中,由一個單一型別的唯一一個建造者接管一系列選項物件。Glide 的generated API進一步簡化了這個操作:它會合並傳入建造者的選項物件和任何已包含的整合庫裡的選項,以生成一個流暢的 API。 ######2、RequestBuilder 對於這類方法:

listener()
thumbnail()
load()
into()

複製程式碼

在 Glide v4 版本中,只存在一個 RequestBuilder 對應一個你正在試圖載入的型別(BitmapDrawableGifDrawable 等)。 RequestBuilder 可以直接訪問對這個載入過程有影響的選項,包括你想載入的資料模型(url, uri等),可能存在的縮圖請求,以及任何的監聽器RequestBuilder也是你使用 into() 或者 preload() 方法開始載入的地方:

RequestBuilder<Drawable> requestBuilder = Glide.with(fragment)
    .load(url);

requestBuilder
    .thumbnail(Glide.with(fragment)
        .load(thumbnailUrl))
    .listener(requestListener)
    .load(url)
    .into(imageView);
複製程式碼

######3、請求選項 對於這類方法:

centerCrop()
placeholder()
error()
priority()
diskCacheStrategy()

複製程式碼

大部分選項被移動到了一個單獨的稱為 RequestOptions 的物件中,

RequestOptions options = new RequestOptions()
    .centerCrop()
    .placeholder(R.drawable.placeholder)
    .error(R.drawable.error)
    .priority(Priority.HIGH);

複製程式碼

RequestOptions 允許你一次指定一系列的選項,然後對多個載入重用它們:

RequestOptions myOptions = new RequestOptions()
    .fitCenter()
    .override(100, 100);

Glide.with(fragment)
    .load(url)
    .apply(myOptions)
    .into(drawableView);

Glide.with(fragment)
    .asBitmap()
    .apply(myOptions)
    .load(url)
    .into(bitmapView);
複製程式碼

######4、變換 Glide v4 裡的 Transformations 現在會替換之前設定的任何變換。在 Glide v4 中,如果你想應用超過一個的 Transformation,你需要使用 transforms() 方法:

Glide.with(fragment)
  .load(url)
  .apply(new RequestOptions().transforms(new CenterCrop(), new RoundedCorners(20)))
  .into(target);

複製程式碼

或使用 generated API:

GlideApp.with(fragment)
  .load(url)
  .transforms(new CenterCrop(), new RoundedCorners(20))
  .into(target);
複製程式碼

######5、解碼格式 在 Glide v3, 預設的 DecodeFormat 是 DecodeFormat.PREFER_RGB_565,它將使用 [Bitmap.Config.RGB_565],除非圖片包含或可能包含透明畫素。對於給定的圖片尺寸,RGB_565 只使用 [Bitmap.Config.ARGB_8888] 一半的記憶體,但對於特定的圖片有明顯的畫質問題,包括條紋(banding)和著色(tinting)。為了避免RGB_565的畫質問題,Glide 現在預設使用 ARGB_8888。結果是,圖片質量變高了,但記憶體使用也增加了。

要將 Glide v4 預設的 DecodeFormat 改回 DecodeFormat.PREFER_RGB_565,請在 AppGlideModule 中應用一個 RequestOption

@GlideModule
public final class YourAppGlideModule extends GlideModule {
  @Override
  public void applyOptions(Context context, GlideBuilder builder) {
    builder.setDefaultRequestOptions(new RequestOptions().format(DecodeFormat.PREFER_RGB_565));
  }
}

複製程式碼

關於使用 AppGlideModules 的更多資訊,請查閱 配置 頁面。請注意,為了讓 Glide 發現你的 AppGlideModule 實現,你必須確保新增了對 Glide 的註解解析器的依賴。關於如何設定這個庫的更多資訊,請檢視 下載和設定。 ######6、過渡選項 對於這類方法:

crossFade()
animate()

複製程式碼

控制從佔位符到圖片和/或縮圖到全圖的交叉淡入和其他型別變換的選項,被移動到了 TransitionOptions 中。

要應用過渡(之前的動畫),請使用下列選項中符合你請求的資源型別的一個:

如果你想移除任何預設的過渡,可以使用 TransitionOptions.dontTransition()]17 。

過渡動畫通過 RequestBuilder 應用到請求上:

Glide.with(fragment)
    .load(url)
    .transition(withCrossFade(R.anim.fade_in, 300));
複製程式碼

######7、交叉淡入 (Cross fade) 不同於 Glide v3,Glide v4 將不會預設應用交叉淡入或任何其他的過渡效果。每個請求必須手動應用過渡。

要為一個特定的載入應用一個交叉淡入變換效果,你可以使用:

import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade;

Glide.with(fragment)
  .load(url)
  .transition(withCrossFade())
  .into(imageView);
複製程式碼

或:

Glide.with(fragment)
  .load(url)
  .transition(
      new DrawableTransitionOptions
        .crossFade())
  .into(imageView);
複製程式碼

######8、Generated API 為了讓使用 Glide v4 更簡單輕鬆,Glide 現在也提供了一套可以為應用定製化生成的 API。應用可以通過包含一個標記了 [AppGlideModule][2 的實現來訪問生成的 API。如果你不瞭解這是怎麼工作的,可以檢視 Generated API 。

Generated API新增了一個 GlideApp 類,該類提供了對 RequestBuilder 和 RequestOptions 子類的訪問。RequestOptions 的子類包含了所有 RequestOptions 中的方法,以及 GlideExtensions 中定義的方法。RequestBuilder 的子類則提供了生成的 RequestOptions 中所有方法的訪問,而不需要你再手動呼叫 apply 。舉個例子:

在沒有使用 Generated API 時,請求大概長這樣:

Glide.with(fragment)
    .load(url)
    .apply(centerCropTransform()
        .placeholder(R.drawable.placeholder)
        .error(R.drawable.error)
        .priority(Priority.HIGH))
    .into(imageView);

複製程式碼

使用 Generated API,RequestOptions 的呼叫可以被內聯:

GlideApp.with(fragment)
    .load(url)
    .centerCrop()
    .placeholder(R.drawable.placeholder)
    .error(R.drawable.error)
    .priority(Priority.HIGH)
    .into(imageView);

複製程式碼

你仍然可以使用生成的 RequestOptions 子類來應用相同的選項到多次載入中;但生成的 RequestBuilder 子類可能在多數情況下更為方便。 ######9、型別(Type)與目標(Target)

選擇資源型別

Glide 允許你指定你想載入的資源型別。如果你指定了一個超型別,Glide 會嘗試載入任何可用的子型別。比如,如果你請求的是 Drawable ,Glide 可能會載入一個 BitmapDrawable 或一個 GifDrawable 。而如果你請求的是一個 GifDrawable ,要麼會載入出一個 GifDrawable,要麼報錯–只要圖片不是 GIF 的話(即使它湊巧是一個完全有效的圖片也是如此)。

預設請求的型別是 Drawable:

Glide.with(fragment).load(url)

複製程式碼

如果要明確指定請求 Bitmap:

Glide.with(fragment).asBitmap()

複製程式碼

如果要建立一個檔案路徑(本地圖片的最佳選項):

Glide.with(fragment).asFile()

複製程式碼

如果要下載一個遠端檔案到快取然後建立檔案路徑:

Glide.with(fragment).downloadOnly()
// or if you have the url already:
Glide.with(fragment).download(url);
複製程式碼

######10、Drawables Glide v3 版本中的 GlideDrawable 類已經被移除,支援標準的Android Drawable。 GlideBitmapDrawable 也已經被刪除,由 BitmapDrawable 代替之。

如果你想知道某個 Drawable 是否是動畫(animated),可以檢查它是否為 Animatable 的例項。

boolean isAnimated = drawable instanceof Animatable;
複製程式碼

######11、Targets onResourceReady 方法的簽名做了一些修改。例如,對於 Drawables:

onResourceReady(GlideDrawable drawable, GlideAnimation<? super GlideDrawable> anim) 

複製程式碼

現在改為:

onResourceReady(Drawable drawable, Transition<? super Drawable> transition);

複製程式碼

類似地, onLoadFailed 的簽名也有一些變動:

onLoadFailed(Exception e, Drawable errorDrawable)

複製程式碼

改為:

onLoadFailed(Drawable errorDrawable)

複製程式碼

如果你想要獲得更多導致載入失敗的錯誤資訊,你可以使用 RequestListener 。 ######12、取消請求 Glide.clear(Target) 方法被移動到了 RequestManager 中:

Glide.with(fragment).clear(target)

複製程式碼

使用 RequestManager 清除之前由它啟動的載入過程,通常能提高效能,雖然這並不是強制要求的。Glide v4 會為每一個 Activity 和 Fragment 跟蹤請求,所以你需要在合適的層級去清除請求。

######13、配置 在 Glide v3 中,配置使用一個或多個 GlideModule 來完成。而在 Glide v4 中,配置改為使用一個類似但稍微複雜的系統來完成。

關於這個新系統的細節,可以檢視配置頁面。

######14、應用程式 在早期版本中使用了一個 GlideModule 的應用,可以將它轉換為一個 AppGlideModule 。

在 Glide v3 中,你可能會有一個像這樣的 GlideModule :

public class GiphyGlideModule implements GlideModule {
  @Override
  public void applyOptions(Context context, GlideBuilder builder) {
    builder.setMemoryCache(new LruResourceCache(10 * 1024 * 1024));
  }

  @Override
  public void registerComponents(Context context, Registry registry) {
    registry.append(Api.GifResult.class, InputStream.class, new GiphyModelLoader.Factory());
  }
}

複製程式碼

在 Glide v4 中,你需要將其轉換成一個 AppGlideModule ,它看起來像這樣:

@GlideModule
public class GiphyGlideModule extends AppGlideModule {
  @Override
  public void applyOptions(Context context, GlideBuilder builder) {
    builder.setMemoryCache(new LruResourceCache(10 * 1024 * 1024));
  }

  @Override
  public void registerComponents(Context context, Registry registry) {
    registry.append(Api.GifResult.class, InputStream.class, new GiphyModelLoader.Factory());
  }
}

複製程式碼

請注意,@GlideModule 註解不能省略。

如果你的應用擁有多個 GlideModule,你需要把其中一個轉換成 AppGlideModule,剩下的轉換成 LibraryGlideModule 。除非存在AppGlideModule ,否則程式不會發現 LibraryGlideModule ,因此您不能僅使用 LibraryGlideModule 。

######15、程式庫 擁有一個或多個 GlideModule 的程式庫應該使用 LibraryGlideModule 。程式庫不應該使用 AppGlideModule ,因為它在一個應用裡只能有一個。因此,如果你試圖在程式庫裡使用它,將不僅會妨礙這個庫的使用者設定自己的選項,還會在多個程式庫都這麼做時造成衝突。

例如,v3 版本中 Volley 整合庫的 GlideModule :

public class VolleyGlideModule implements GlideModule {
  @Override
  public void applyOptions(Context context, GlideBuilder builder) {
    // Do nothing.
  }

  @Override
  public void registerComponents(Context context, Registry registry) {
    registry.replace(GlideUrl.class, InputStream.class, new VolleyUrlLoader.Factory(context));
  }
}

複製程式碼

在 v4 版本中可以轉換成為一個 LibraryGlideModule :

@GlideModule
public class VolleyLibraryGlideModule extends LibraryGlideModule {
  @Override
  public void registerComponents(Context context, Registry registry) {
    registry.replace(GlideUrl.class, InputStream.class, new VolleyUrlLoader.Factory(context));
  }
}
複製程式碼

######16、清單解析

為了簡化遷移過程,儘管清單解析和舊的 GlideModule 介面已被廢棄,但它們在 v4 版本中仍被支援。AppGlideModuleLibraryGlideModule,與已廢棄的 GlideModule 可以在一個應用中共存。

然而,為了避免檢查後設資料的效能天花板(以及相關的 bugs ),你可以在遷移完成後禁用掉清單解析,在你的 AppGlideModule 中複寫一個方法:

@GlideModule
public class GiphyGlideModule extends AppGlideModule {
  @Override
  public boolean isManifestParsingEnabled() {
    return false;
  }

  ...
}
複製程式碼

######17、using(), ModelLoader, StreamModelLoader.

ModelLoader

ModelLoader API 在 v4 版本中仍然存在,並且它的設計目標仍然和它在 v3 中一樣,但有一些細節變化。

第一個細節,ModelLoader 的子型別如 StreamModelLoader ,現在已沒有存在的必要,使用者可以直接實現 ModelLoader 。例如,一個StreamModelLoader<File> 類現在可以通過 ModelLoader<File, InputStream> 的方式來實現和引用。

第二, ModelLoader 現在並不直接返回 DataFetcher,而是返回 LoadData 。[LoadData] 是一個非常簡單的封裝,包含一個磁碟快取鍵和一個 DataFetcher

第三, ModelLoaders 有一個 handles() 方法,這使你可以為同一個型別引數註冊超過一個的 ModelLoader 。

將一個 ModelLoader 從 v3 API轉換到 v4 API ,通常是很簡單直接的。如果你在你的 v3 ModelLoader 中只是簡單滴返回一個 DataFetcher :

public final class MyModelLoader implements StreamModelLoader<File> {

  @Override
  public DataFetcher<InputStream> getResourceFetcher(File model, int width, int height) {
    return new MyDataFetcher(model);
  }
}

複製程式碼

那麼你在 v4 替代類上需要做的僅僅只是封裝一下這個 data fetcher :

public final class MyModelLoader implements ModelLoader<File, InputStream> {

  @Override
  public LoadData<InputStream> buildLoadData(File model, int width, int height,
      Options options) {
    return new LoadData<>(model, new MyDataFetcher(model));
  }

  @Override
  public void handles(File model) {
    return true;
  }
}

複製程式碼

請注意,除了 DataFetcher 之外,模型也被傳遞給 LoadData 作為快取鍵的一部分。這個規則為某些特殊場景提供了更多對磁碟快取鍵的控制。大部分實現可以直接將 model 傳入 LoadData ,就像上面這樣。

如果你僅僅是想為某些 model(而不是所有)使用你的 ModelLoader,你可以在你嘗試載入 model 之前使用 handles() 方法來檢查它。如果你從 handles 方法中返回了 false ,那麼你的 ModelLoader 將不能載入指定的 model ,即使你的 ModelLoader 型別 (在這個例子裡是 File 和 InputStream) 與之匹配。

舉個例子,如果你在某個指定資料夾下寫入了加密的圖片,你可以使用 handles 方法來實現一個 ModelLoader 以從那個特定的資料夾下解密圖片,但是並不用於載入其他資料夾下的 File :

public final class MyModelLoader implements ModelLoader<File, InputStream> {
  private static final String ENCRYPTED_PATH = "/my/encrypted/folder";

  @Override
  public LoadData<InputStream> buildLoadData(File model, int width, int height,
      Options options) {
    return new LoadData<>(model, new MyDataFetcher(model));
  }

  @Override
  public void handles(File model) {
    return model.getAbsolutePath().startsWith(ENCRYPTED_PATH);
  }
}

複製程式碼

using()

using API在 Glide v4 中被刪除了,這是為了鼓勵使用者使用 AppGlideModule 一次性地 註冊 所有元件,避免物件重用(re-use, 原文如此 –譯者注)。你無需每次載入圖片時都建立一個新的 ModelLoader ;你應該在 AppGlideModule 中註冊一次,然後交給 Glide 在每次載入時檢查 model (即你傳入 load() 方法的物件)來決定什麼時候使用你註冊的 ``ModelLoader` 。

為了確保你僅為特定的 model 使用你的 ModelLoader ,請像上面展示的那樣實現 handles 方法:檢查每個 model ,但僅在應當使用你的 ModelLoader 時才返回 true 。

##以上17點就是Glide4.X和Glide3.X的區別,還是建議看官方文件

相關文章