Android Glide簡單使用

轉載自    https://blog.csdn.net/bzlj2912009596/article/details/81702367
今天,簡單講講Android裏Glide的簡單使用。

對於Glide這個加載圖片的框架,很多人都在用,我之前使用的是ImageLoader,最近查資料時,發現Glide纔是Google推薦的加載圖片框架,功能非常強大,而且還有Google專人維護,要知道,ImageLoader已經沒人維護了,除了問題可沒人解答。所以有必要整理一下Glide的使用。

Glide是谷歌爲我們推薦的一個圖片加載庫。爲什麼要選擇使用Glide呢?

1、代碼有人維護,不至於出現問題,項目組都搞不定的時候問題無法解決。(ImageLoader已沒人維護了)
2、代碼簡潔,可讀性很好。(Fresco是一個非常優秀的庫,但是配置稍顯麻煩,同時代碼風格讀起來有些生疏)
3、功能強大(400多k的包,包含很多功能,例如:像加載Gif圖片就是Picasso做不到的)
下面我們就來介紹下Glide的用法:

Glide的基本使用
導入庫
compile 'com.github.bumptech.glide:glide:3.7.0'
添加代碼混淆(可加可不加)
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}
 
# for DexGuard only
-keepresourcexmlelements manifest/application/meta-data@value=GlideModule
這個別忘了,不要粗心哦,很容易忘得,最簡單的問題,往往需要最簡單的搞定啦。

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
簡單使用例子
// For a simple view:
@Override 
public void onCreate(Bundle savedInstanceState) {
  ...
  ImageView imageView = (ImageView) findViewById(R.id.my_image_view);
 
  Glide.with(this).load("http://goo.gl/gEgYUd").into(imageView);
}
 
// For a simple image list:
@Override 
public View getView(int position, View recycled, ViewGroup container) {
  final ImageView myImageView;
  if (recycled == null) {
    myImageView = (ImageView) inflater.inflate(R.layout.my_image_view, container, false);
  } else {
    myImageView = (ImageView) recycled;
  }
 
  String url = myUrls.get(position);
 
  Glide
    .with(myFragment)
    .load(url)
    .centerCrop()
    .placeholder(R.drawable.loading_spinner)
    .crossFade()
    .into(myImageView);
 
  return myImageView;
}
Glide使用詳解
加載網絡圖片
Glide.with(context).load(internetUrl).into(targetImageView);
從文件加載圖片
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),"Test.jpg");
Glide.with(context).load(file).into(imageViewFile);
從資源id加載圖片
int resourceId = R.mipmap.ic_launcher;
Glide.with(context).load(resourceId).into(imageViewResource);
從uri加載圖片
Glide.with(context).load(uri).into(imageViewUri);
播放本地mp4,只能是本地(獲取MP4視頻的縮略圖)
String filePath = "/storage/emulated/0/Pictures/example_video.mp4";
Glide.with( context ).load( Uri.fromFile( **new **File( filePath ) ) ).into( imageViewGifAsBitmap );
加載Gif圖片
String gifUrl = "xxxxx";
Glide.with( context ).load( gifUrl ).into( imageViewGif );
用bitMap播放Gif.asBitmap()
Glide.with( context ).load( gifUrl ).asBitmap().into( imageViewGifAsBitmap );
強制轉化爲Gif.asGif()
Glide.with( context ).load( gifUrl ).asGif().error( R.drawable.full_cake ).into( imageViewGif );
設置默認佔位圖.placeholder()
設置加載失敗的圖片.error()
Glide.with( context ).load( gifUrl ).placeholder( R.drawable.cupcake ).error( R.drawable.full_cake ).into( imageViewGif );
.fallback()
除了上面兩種‘異常情況’,還有一種情形就是打開手機的通訊錄的時候,可以看到你給有些喜歡的人設置了照片,然而有些可憐的人並沒給有,總不能在那裏留下一片空白吧,這個時候相當於傳遞了Null,傳遞null時,這個callback方法就會被調用。

Glide.with(context)
     .load( null)//加載空指針的時候
     .fallback( R.drawable.wuyanzu)
     .into( imageViewNoFade );
設置加載動畫
其實這個是默認的,但是你還是可以寫出來,漸顯動畫
1、.crossFade() :Glide提供淡如淡出

Glide.with(context).load().placeholder(R.mipmap.ic_launcher) .error(R.mipmap.future_studio_launcher).crossFade().into(imageViewFade);
這裏還有一個.fadeFade(int duration),設置動畫時間。如果你不想要動畫可以加上.dontAnimate()
2、.animate(android.R.anim.slide_in_left):Android系統提供,從左到右滑出加載動畫

調整圖片大小.resize(int ,int )
單位是像素,裁剪你的圖片大小。其實Glide已經會自動根據你ImageView裁剪照片來放在緩存中了。但是不想適應ImageView大小的時候,可以調用這個方法.override()爲ImageView指定大小。

Glide.with(context).load(image).override(600, 200) .into(imageViewResize);
裁剪圖片.fitCenter()和.CenterCrop()
Glide清楚在合適的ImageView中加載合適的Image.當需要裁剪大小時,有個.centerCrop方法,這個方法的裁剪會讓你的ImageView周圍不會留白,還有一個.fitCenter()方法,表示讓你的Image完全顯示,尺寸不對時,周圍會留白。

設置縮略圖.thumbnail()
.thumbnail()方法的目的就是讓用戶先看到一個低解析度的圖,點開後,再加載一個高解析度的圖。

//表示爲原圖的十分之一
Glide.with( context ).load(image).thumbnail( 0.1f ).into( imageView2 );
一種更高級的縮略圖加載方式:

當縮略圖也需要通過網絡加載全部解析度的時候。

private void loadImageThumbnailRequest() {
    DrawableRequestBuilder<String> thumbnailRequest = Glide.with( context ).load( eatFoodyImages[2] );
    Glide.with( context ).load( UsageExampleGifAndVideos.gifUrl ).thumbnail( thumbnailRequest ).into( imageView3 );
}
設置圖片顯示效果(圓角、圓形、高斯模糊、蒙板、裁剪等等).bitmapTransform()
Glide.with(this).load(R.mipmap.ic_image_sample)
     //模糊
     .bitmapTransform(new BlurTransformation(this))
     //圓角
     .bitmapTransform(new RoundedCornersTransformation(this, 24, 0, RoundedCornersTransformation.CornerType.ALL))
     //遮蓋
     .bitmapTransform(new MaskTransformation(this, R.mipmap.ic_launcher))
     //灰度
     .bitmapTransform(new GrayscaleTransformation(this))
     //圓形
     .bitmapTransform(new CropCircleTransformation(this))
     .into(mResultIv);
除此之外還有實現諸如馬賽克、明暗度等更多濾鏡處理:

ToonFilterTransformation
SepiaFilterTransformation
ContrastFilterTransformation
InvertFilterTransformation
PixelationFilterTransformation
SketchFilterTransformation
SwirlFilterTransformation
BrightnessFilterTransformation
KuwaharaFilterTransformation
VignetteFilterTransformation
Glide的緩存
用過手機的都知道,當劃上劃下一個ListView的時候,第二次都比第一次快,就是因爲爲GlideView對資源進行了緩存,而且封裝的很好,甚至不需要自己去設定緩存大小,Glide會智能地自己給我們根據設備設置緩存大小。

緩存是爲了減少或者杜絕多的網絡請求。爲了避免緩存,Glide用了內存緩存和‘外存緩存機制’,並且 提供了相應的方法,完全封裝,不需要處理細節。Glide會自動緩存到內存,除非調用.skipMemoryCache( true )。儘管調用了這個,Glide還是會緩存到外存,還有一種情形,就是有一張圖片,但是這張圖變化非常快,這個時候可能並不想緩存到外存中,就使用.diskCacheStrategy( DiskCacheStrategy.NONE )。如果你兩種都不需要,可以兩個方法組合着一起使用。

自定義外存緩存機制

Glide默認會緩存Image的很多個版本,比如原圖,如果你的imageView大小的緩存。.diskCacheStrategy()有以下幾種緩存策略:

DiskCacheStrategy.NONE 什麼都不緩存
DiskCacheStrategy.SOURCE 只緩存最高解析圖的image
DiskCacheStrategy.RESULT 緩存最後一次那個image,比如有可能你對image做了轉化
DiskCacheStrategy.ALL image的所有版本都會緩存
Glide.with( context ).load( image ).diskCacheStrategy( DiskCacheStrategy.SOURCE ).into( imageViewFile );
修改緩存大小、位置、加載圖片質量

和指定HttpClent爲OkHttp一樣,只不過我們需要配置一些信息在applyOptions()函數裏面

public class GlideConfigModule implements GlideModule {
    @Override
    public void applyOptions(Context context, GlideBuilder builder) {
        // 指定位置在packageName/cache/glide_cache,大小爲MAX_CACHE_DISK_SIZE的磁盤緩存
        builder.setDiskCache(new InternalCacheDiskCacheFactory(context, "glide_cache", ConfigConstants.MAX_CACHE_DISK_SIZE));
        //指定內存緩存大小
        builder.setMemoryCache(new LruResourceCache(ConfigConstants.MAX_CACHE_MEMORY_SIZE));
        //全部的內存緩存用來作爲圖片緩存
        builder.setBitmapPool(new LruBitmapPool(ConfigConstants.MAX_CACHE_MEMORY_SIZE));
        builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);//和Picasso配置一樣
    }
 
    @Override
    public void registerComponents(Context context, Glide glide) {
    }
}
 <meta-data            android:name="com.example.imageloadpk.adapter.config.GlideConfigModule"
            android:value="GlideModule"/>
一般的圖片加載框架設置了磁盤緩存和內存緩存就行了,但是Glide還設置了一個圖片緩存。
圖片緩存 <= 內存緩存

builder.setDiskCache(new InternalCacheDiskCacheFactory(context, "glide_cache", ConfigConstants.MAX_CACHE_DISK_SIZE));
        //指定內存緩存大小
        builder.setMemoryCache(new LruResourceCache(ConfigConstants.MAX_CACHE_MEMORY_SIZE));
        //全部的內存緩存用來作爲圖片緩存
        builder.setBitmapPool(new LruBitmapPool(ConfigConstants.MAX_CACHE_MEMORY_SIZE));
這裏Glide不僅可以緩存圖片,還可以緩存其他文件譬如視頻之類,也就是說可以把他作爲我們的緩存工具來使用,當然緩存方式還是使用LRU。這樣我們就不必再去重新集成LruCache和DiskLruCache,再去申請空間,配置。直接可以複用Glide的。

使用緩存也加載動畫

但是,動畫默認是在圖片沒有緩存的情況下才加載,想想也是合理的,如果圖片已近下載到本地加載速度將會非常快,這個時候使用動畫過渡反而礙事。要讓從緩存中圖片呈現也加載動畫不能通過這種方式實現,可以用監聽器來做。

   private RequestListener<String, GlideBitmapDrawable> mAnimationRequestListener = new RequestListener<String, GlideBitmapDrawable>() {
        @Override
        public boolean onException(Exception e, String model, Target<GlideBitmapDrawable> target, boolean isFirstResource) {
            return false;
        }
 
        @Override
        public boolean onResourceReady(GlideBitmapDrawable resource, String model, Target<GlideBitmapDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
            dissProgress();
            if (isFromMemoryCache) {
            //如果是從緩存加載,設置動畫效果
                mIvShow.setAnimation(AnimationUtils.loadAnimation(mContext, R.anim.scale));
            }
            //返回true表示攔截不再傳遞,false表示事件會傳遞下去
            return false;
        }
    };
請求優先級.priority()
加載圖片肯定也是有先後順序,Glide提供了.priority()這個方法,它接收以下幾個參數:

Priority.LOW
Priority.NORMAL
Priority.HIGH
Priority.IMMEDIATE
但是Glide並不一定會按照你的順序來,只是儘量按照你的順序來。(比如給一張很大的圖片最高的優先權,但是它並不一定比低優先級的圖先加載出來,這個時候只有使用縮略圖了)

Glide.with(mContext).load(Url.IMAGE_URL_TROCHILIDAE)
     .priority(Priority.HIGH).into(mIvTonyRight);
利用callback在非標準情況下加載圖片
上面所有的情況都是加載圖片到ImageView中,但是並不是所有的情況都是這樣。譬如加載的控件類型不是ImageView,是個自定義的佈局。或者加載爲Background的形式。
可以使用SimpleTarget類型,這裏指定他的大小爲500*100,加載爲背景圖片

.into(new SimpleTarget<Drawable>(500, 100) {
    @Override
    public void onResourceReady(Drawable resource, GlideAnimation<? super Drawable> glideAnimation) {
        mBtnClear.setBackground(resource);
    }
同理下載圖片原理是一樣

.into(new SimpleTarget<Bitmap>() {
    @Override
    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
        //toSave
        Log.d(TAG, "onResourceReady: save successful");
    }
});
Glide中的回調:Targets

從上面的介紹,已經可以看出Glide內部封裝了所有的細節,什麼網絡請求,什麼緩存機制,當所有都就緒過後,自動切換回UI線程,更新ImageView。Targets就是Glide中的回調,當異步線程中所有的工作做完過後返回結果。說白了就是,當請求圖片完成後,需要回調的方法。

SimpleTarget

private SimpleTarget target = new SimpleTarget<Bitmap>() {
    @Override
    public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {
        // do something with the bitmap
        // for demonstration purposes, let's just set it to an ImageView
        imageView1.setImageBitmap( bitmap );
    }
};
 
private void loadImageSimpleTarget() {
    Glide.with( context ) *// could be an issue!*
         .load( eatFoodyImages[0] )
         .asBitmap()//強制Glide返回一個Bitmap
         .into( target );
}
注意事項:

1、上面這段代碼不要寫成匿名內部類的機制,原因就是java的自動垃圾回收機制可能在圖片還沒有加載好的時候就已經把你的Target回收了。

2、注意.with()裏面的參數,Glide的請求是和傳進去的Context共存亡的,如果傳一個Activity進去,當Activity GC過後,你的請求也就GC了,但是如果這樣傳:.with(context.getApplicationContext() ).當你的Activity GC過後,請求還是會繼續,回調還是會繼續。
有size的Target

如果傳給into().的是一個ImageView,但是圖片的size比ImageView的Size打,Glide爲了節省時間,會加載小的那個size的Image。但是這對Target並不適用,以爲這裏並不知道SIze。但是如果知道image應該多大,可以傳遞給Target.就像下面這樣:

private SimpleTarget target2 = new SimpleTarget<Bitmap>( 250, 250 ) {
    @Override
    public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {
        imageView2.setImageBitmap( bitmap );
    }
};
 
private void loadImageSimpleTargetApplicationContext() {
    Glide.with(context.getApplicationContext()); *// safer!*
         .load( eatFoodyImages[1] )
         .asBitmap()
         .into( target2 );
}
ViewTarget

適用於想Glide加載到自定義View中去,

public class FutureStudioView extends FrameLayout {
    ImageView iv;
    TextView tv;
 
    public void nitialize(Context context) {
        inflate( context, R.layout.custom_view_futurestudio, this );
        iv = (ImageView) findViewById( R.id.custom_view_image );
        tv = (TextView) findViewById( R.id.custom_view_text );
    }
 
    public FutureStudioView(Context context, AttributeSet attrs) {
        super( context, attrs );
        initialize( context );
    }
 
    public FutureStudioView(Context context,AttributeSet attrs,int defStyleAttr) {
        super( context, attrs, defStyleAttr );
        initialize( context );
    }
 
    public void setImage(Drawable drawable) {
        iv = (ImageView) findViewById( R.id.custom_view_image );
        iv.setImageDrawable( drawable );
    }
}
還有notificationTarget 和AppWidget作爲擴展自行研究嘍。

監聽器配置.listener()
Glide.with(getContext()).load(url)
     .listener(mRequestListener)//配置監聽器
     .placeholder(Drawables.sPlaceholderDrawable)
     .error(Drawables.sErrorDrawable)
     .into(mImageView);
 
private RequestListener<String, GlideDrawable> mRequestListener = new RequestListener<String, GlideDrawable>() {
        @Override
        public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
            //顯示錯誤信息
            Log.w(TAG, "onException: ", e);
            //打印請求URL
            Log.d(TAG, "onException: " + model);
            //打印請求是否還在進行
            Log.d(TAG, "onException: " + target.getRequest().isRunning());
            return false;
        }
 
        @Override
        public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
            return false;
        }
    };
這裏的onException捕獲異常,如果返回true表示我們自己處理掉了異常,false表示交給Glide去處理,因爲我們定義了.error()那麼就顯示error裏面的內容。

這裏onResourceReady表示是否準備資源顯示,返回true表示用戶自己已經設置好資源,包括截取操作,動畫操作之類的,準備好顯示。false表示交給Glide

如此修改後,就能夠看到圖片加載日誌了,方便我們調試

替換掉自帶的HttpClient
只需兩步
Step1:
導入需要替換的HttpClient,可以選擇Volley也可以選擇OkHttp,我們使用Okhttp,在Module的build.gradle文件中配置

dependencies {
    compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar'
    compile 'com.squareup.okhttp3:okhttp:3.3.1'
 
    or
 
    compile 'com.github.bumptech.glide:volley-integration:1.4.0@aar'
    compile 'com.mcxiaoke.volley:library:1.0.8'
}
這個版本具體選擇多少,可以在https://github.com/bumptech/glide/wiki/Integration-Libraries這裏查詢到
Step2:
在AndroidMainfest.xml文件中寫入

這個版本具體選擇多少,可以在https://github.com/bumptech/glide/wiki/Integration-Libraries這裏查詢到
Step2:
在AndroidMainfest.xml文件中寫入

 <meta-data         android:name="com.bumptech.glide.integration.okhttp3.OkHttpGlideModule"
            android:value="GlideModule"/>
你可能會有和我一樣的疑問,Glide可以通過在配置清單裏面配置
能不能寫幾個meta-data標籤,一個標籤裏面配置一點參數
經過測試,發現這樣做也是可以的。但是如果是同一種配置信息,比如你集成了OkHttp,又寫一個標籤集成Volley,最後一個會把前面的覆蓋掉。

注意事項
1、前面我們已經學習到asGif()可以加載gif圖,asBitmap()可以加載靜態gif圖即gif圖的第一幀,如果非gif圖用asGif()方法加載呢?這時候會報錯。。Glide默認可以自動識別圖片格式,加載gif圖,所以在不確定圖片格式的情況下,不要直接寫asGif哦。

2、You cannot start a load for a destroyed activity這樣的異常如何處理?
記住不要再非主線程裏面使用Glide加載圖片,如果真的使用了,請把context參數換成getApplicationContext。希望可以幫你避免這個問題。

3、爲什麼有的圖片第一次加載的時候只顯示佔位圖,第二次才顯示正常的圖片呢?
.如果你剛好使用了這個圓形Imageview庫或者其他的一些自定義的圓形Imageview,而你又剛好設置了佔位的話,那麼,你就會遇到第一個問題。如何解決呢?

方案一: 不設置佔位;
方案二:使用Glide的Transformation API自定義圓形Bitmap的轉換。這裏是一個已有的例子;
方案三:使用下面的代碼加載圖片:

Glide.with(mContext)
    .load(url) 
    .placeholder(R.drawable.loading_spinner)
    .into(new SimpleTarget<Bitmap>(width, height) {
        @Override 
        public void onResourceReady(Bitmap bitmap, GlideAnimation anim) {
            // setImageBitmap(bitmap) on CircleImageView 
        } 
    };
4、圖片大小拉伸問題
有時候你會發現網絡加載完了之後會有拉伸現象,而你的控件大小明明是自適應的呀,這是爲什麼呢,請你檢查下你是否設置了佔位圖,有的話請去掉就ok了。

 

簡單總結一下,我這裏講了Glide比較全面的用法,有如何加載圖片,Glide的緩衝設置,Glide設置圓角,Glide設置圖片的background,Glide加載GIF圖片等,大家使用的話一般瞭解加載圖片和圓角圖片就可以了。這裏在列舉一下。

 //圓形裁剪
    Glide.with(this)
        .load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png")
        .bitmapTransform(new CropCircleTransformation(this))
        .into(iv_0);
    //圓角處理
    Glide.with(this)
        .load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png")
        .bitmapTransform(new RoundedCornersTransformation(this,30,0, RoundedCornersTransformation.CornerType.ALL))
        .into(iv_0);
android Glide簡單使用就講完了。

就這麼簡單。
--------------------- 
作者:暴走鄰家 
來源:CSDN 
原文:https://blog.csdn.net/bzlj2912009596/article/details/81702367 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

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