1、在build.gradle中添加依賴:? ??
compile 'com.github.bumptech.glide:glide:3.7.0'
需要support-v4庫的支持,如果你的項(xiàng)目沒有support-v4庫(項(xiàng)目默認(rèn)已經(jīng)添加了),還需要添加support-v4依賴:? ? ?
?compile'com.Android.support:support-v4:23.3.0'
2、然后配置混淆規(guī)則:
-keeppublicclass
?*implements
?com.bumptech.glide.module.GlideModule
-keeppublic
enum?
com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$**
?{
**[] $VALUES;
public *;
?}
其中第一個(gè)混淆規(guī)則表明不混淆所有的GlideModule。
?如果需要的話,還需添加相應(yīng)的權(quán)限:
3、 使用Glide.with(this).load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png").into(imageView);
Glide.with()
使用with(Context context). 使用Application上下文,Glide請求將不受Activity/Fragment生命周期控制。
with(Activity activity).使用Activity作為上下文,Glide的請求會(huì)受到Activity生命周期控制。with(FragmentActivity activity).Glide的請求會(huì)受到FragmentActivity生命周期控制。with(android.app.Fragment fragment).Glide的請求會(huì)受到Fragment 生命周期控制。with(android.support.v4.app.Fragment fragment).Glide的請求會(huì)受到Fragment生命周期控制。
requestManager.load()
使用Glide基本可以load任何可以拿到的媒體資源,如:
?load SD卡資源:load("file://"+ Environment.getExternalStorageDirectory().getPath()+"/test.jpg") load assets資源:load("file:///android_asset/f003.gif") load raw資源:load("Android.resource://com.frank.glide/raw/raw_1")或load("android.resource://com.frank.glide/raw/"+R.raw.raw_1) load drawable資源:load("android.resource://com.frank.glide/drawable/news")或load("android.resource://com.frank.glide/drawable/"+R.drawable.news) load ContentProvider資源:load("content://media/external/images/media/139469") load http資源:load("http://cn.bing.com/az/hprichbg/rb/Dongdaemun_ZH-CN10736487148_1920x1080.jpg") load https資源:load(" http://cn.bing.com/az/hprichbg/rb/Dongdaemun_ZH-CN10736487148_1920x1080.jpg ")?
當(dāng)然,load不限于String類型,還可以:??
?load(Uri uri),load(File file),load(Integer resourceId),load(URL url),load(byte[] model),load(T model),loadFromMediaStore(Uri uri)。?
load的資源也可以是本地視頻,如果想要load網(wǎng)絡(luò)視頻或更高級的操作可以使用VideoView等其它控件完成。?
而且可以使用自己的ModelLoader進(jìn)行資源加載:
? using(ModelLoadermodelLoader, ClassdataClass),using(final StreamModelLoadermodelLoader),using(StreamByteArrayLoader modelLoader),using(final FileDescriptorModelLoadermodelLoader)。?
返回GenericRequestBuilder實(shí)例。
GenericRequestBuilder使用
GenericRequestBuilder是最頂層的Request Builder,用于處理選項(xiàng)設(shè)置和開始一般resource類型資源的加載。其中ModelType是指代表資源的類型,如"http://img.my.csdn.net/uploads/201508/05/1438760757_3588.jpg"這個(gè)String就代表了一張圖片資源,所以這個(gè)ModelType就是String。DataType是指ModelLoader提供的,可以被ResourceDecoder解碼的數(shù)據(jù)類型。ResourceType是指將要加載的resource類型。TranscodeType是指已解碼的資源將要被轉(zhuǎn)成的資源類型。
1、thumbnail(float sizeMultiplier). 請求給定系數(shù)的縮略圖。如果縮略圖比全尺寸圖先加載完,就顯示縮略圖,否則就不顯示。系數(shù)sizeMultiplier必須在(0,1)之間,可以遞歸調(diào)用該方法。
2、sizeMultiplier(float sizeMultiplier). 在加載資源之前給Target大小設(shè)置系數(shù)。
3、diskCacheStrategy(DiskCacheStrategy strategy).設(shè)置緩存策略。DiskCacheStrategy.SOURCE:緩存原始數(shù)據(jù),DiskCacheStrategy.RESULT:緩存變換(如縮放、裁剪等)后的資源數(shù)據(jù),DiskCacheStrategy.NONE:什么都不緩存,DiskCacheStrategy.ALL:緩存SOURC和RESULT。默認(rèn)采用DiskCacheStrategy.RESULT策略,對于download only操作要使用DiskCacheStrategy.SOURCE。
4、priority(Priority priority). 指定加載的優(yōu)先級,優(yōu)先級越高越優(yōu)先加載,但不保證所有圖片都按序加載。枚舉Priority.IMMEDIATE,Priority.HIGH,Priority.NORMAL,Priority.LOW。默認(rèn)為Priority.NORMAL。
5、dontAnimate(). 移除所有的動(dòng)畫。
6、animate(int animationId). 在異步加載資源完成時(shí)會(huì)執(zhí)行該動(dòng)畫。
7、animate(ViewPropertyAnimation.Animator animator). 在異步加載資源完成時(shí)會(huì)執(zhí)行該動(dòng)畫。
8、placeholder(int resourceId). 設(shè)置資源加載過程中的占位Drawable。
9、placeholder(Drawable drawable). 設(shè)置資源加載過程中的占位Drawable。
10、fallback(int resourceId). 設(shè)置model為空時(shí)要顯示的Drawable。如果沒設(shè)置fallback,model為空時(shí)將顯示error的Drawable,如果error的Drawable也沒設(shè)置,就顯示placeholder的Drawable。
11、fallback(Drawable drawable).設(shè)置model為空時(shí)顯示的Drawable。
12、error(int resourceId).設(shè)置load失敗時(shí)顯示的Drawable。
13、error(Drawable drawable).設(shè)置load失敗時(shí)顯示的Drawable。
14、listener(RequestListenerrequestListener). 監(jiān)聽資源加載的請求狀態(tài),可以使用兩個(gè)回調(diào):onResourceReady(R resource, T model, Targettarget, boolean isFromMemoryCache, boolean isFirstResource)和onException(Exception e, T model, Target target, boolean isFirstResource),但不要每次請求都使用新的監(jiān)聽器,要避免不必要的內(nèi)存申請,可以使用單例進(jìn)行統(tǒng)一的異常監(jiān)聽和處理。
15、skipMemoryCache(boolean skip). 設(shè)置是否跳過內(nèi)存緩存,但不保證一定不被緩存(比如請求已經(jīng)在加載資源且沒設(shè)置跳過內(nèi)存緩存,這個(gè)資源就會(huì)被緩存在內(nèi)存中)。
16、override(int width, int height). 重新設(shè)置Target的寬高值(單位為pixel)。
17、into(Y target).設(shè)置資源將被加載到的Target。
18、into(ImageView view). 設(shè)置資源將被加載到的ImageView。取消該ImageView之前所有的加載并釋放資源。
19、into(int width, int height). 后臺線程加載時(shí)要加載資源的寬高值(單位為pixel)。
20、preload(int width, int height). 預(yù)加載resource到緩存中(單位為pixel)。
21、asBitmap(). 無論資源是不是gif動(dòng)畫,都作為Bitmap對待。如果是gif動(dòng)畫會(huì)停在第一幀。
22、asGif().把資源作為GifDrawable對待。如果資源不是gif動(dòng)畫將會(huì)失敗,會(huì)回調(diào).error()。
4、技巧
?1、禁止內(nèi)存緩存:? ?
?.skipMemoryCache(true)
2、清除內(nèi)存緩存:? ?
?// 必須在UI線程中調(diào)用? ??
Glide.get(context).clearMemory();
3、禁止磁盤緩存:
? .diskCacheStrategy(DiskCacheStrategy.NONE)
4、清除磁盤緩存:?
?// 必須在后臺線程中調(diào)用,建議同時(shí)clearMemory()? Glide.get(applicationContext).clearDiskCache();
5、獲取緩存大小:?
new GetDiskCacheSizeTask(textView).execute(new File(getCacheDir(), DiskCache.Factory.DEFAULT_DISK_CACHE_DIR));11class GetDiskCacheSizeTask extends AsyncTask{
private final TextView resultView;
public GetDiskCacheSizeTask(TextView resultView) {
this.resultView = resultView;
}
@Override
protected void onPreExecute() {
resultView.setText("Calculating...");
}
@Override
protected void onProgressUpdate(Long... values) { /* onPostExecute(values[values.length - 1]); */ }
@Override
protected Long doInBackground(File... dirs) {
try {
long totalSize = 0;
for (File dir : dirs) {
publishProgress(totalSize);
totalSize += calculateSize(dir);
}
return totalSize;
} catch (RuntimeException ex) {
final String message = String.format("Cannot get size of %s: %s", Arrays.toString(dirs), ex);
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
resultView.setText("error");
Toast.makeText(resultView.getContext(), message, Toast.LENGTH_LONG).show(); ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
?return 0L;
}
@Override
protected void onPostExecute(Long size) {
String sizeText = android.text.format.Formatter.formatFileSize(resultView.getContext(), size);
resultView.setText(sizeText);
}
private static long calculateSize(File dir) {
if (dir == null) return 0;
if (!dir.isDirectory()) return dir.length();
long result = 0;
File[] children = dir.listFiles();
if (children != null)
for (File child : children)
result += calculateSize(child);
return result;}
}
6、指定資源的優(yōu)先加載順序:??
//優(yōu)先加載
? ? ?Glide
? ? ? ? ? ? ?.with(context)
? ? ? ? ? ? ?.load(heroImageUrl)
? ? ? ? ? ? .priority(Priority.HIGH)
? ? ? ? ? ? .into(imageViewHero);
//后加載
? ? ? ?Glide
? ? ? ? ? ? .with(context)
? ? ? ? ? ? .load(itemImageUrl)
? ? ? ? ? ?.priority(Priority.LOW)
? ? ? ? ? ? .into(imageViewItem);
7、先顯示縮略圖,再顯示原圖:? ?
//用原圖的1/10作為縮略圖? ? Glide? ? ? ?
?.with(this) ? ? ? ? ? ? ? ?.load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png") ? ? ? ? .thumbnail(0.1f)? ? ? ? .into(iv_0);? ? //用其它圖片作為縮略圖 ? ? ? ?DrawableRequestBuilderthumbnailRequest = Glide
.with(this)
.load(R.drawable.news);
Glide.with(this)
.load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png")
.thumbnail(thumbnailRequest)
.into(iv_0);
8、對圖片進(jìn)行裁剪、模糊、濾鏡等處理:
?推薦使用獨(dú)立的圖片處理庫:wasabeef/glide-transformations,使用也很簡單:?
?? compile 'jp.wasabeef:glide-transformations:2.0.0'
之后我們就可以使用GenericRequestBuilder或其子類的transform()或bitmapTransform()方法設(shè)置圖片轉(zhuǎn)換了:? ?
?//圓形裁剪? ? 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); ??
?//灰度處理? ?
?Glide.with(this)? ? ? ? .load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png")? ? ? ? .bitmapTransform(new GrayscaleTransformation(this)) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??.into(iv_0); ? ?
//其它變換...
5、 Glide有哪些“坑”?
1、ImageView的setTag問題 問題描述: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??如果使用Glide的into(imageView)為ImageView設(shè)置圖片的同時(shí)使用ImageView的setTag(final Object tag)方法,將會(huì)導(dǎo)致java.lang.IllegalArgumentException: You must not call setTag() on a view Glide is targeting異常。因?yàn)镚lide的ViewTarget中通過view.setTag(tag)和view.getTag()標(biāo)記請求的,由于Android 4.0之前Tag存儲在靜態(tài)map里,如果Glide使用setTag(int key, final Object tag)方法標(biāo)記請求則可能會(huì)導(dǎo)致內(nèi)存泄露,所以Glide默認(rèn)使用view.setTag(tag)標(biāo)記請求,你就不能重復(fù)調(diào)用了。 解決辦法:如果你需要為ImageView設(shè)置Tag,必須使用setTag(int key, final Object tag)及getTag(int key)方法,其中key必須是合法的資源ID以確保key的唯一性,典型做法就是在資源文件中聲明type="id"的item資源。
2、placeholder()導(dǎo)致的圖片變形問題 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?問題描述:使用.placeholder()方法在某些情況下會(huì)導(dǎo)致圖片顯示的時(shí)候出現(xiàn)圖片變形的情況。這是因?yàn)镚lide默認(rèn)開啟的crossFade動(dòng)畫導(dǎo)致的TransitionDrawable繪制異常,詳細(xì)描述和討論可以看一下這個(gè)#363 issue。根本原因就是你的placeholder圖片和你要加載顯示的圖片寬高比不一樣,而Android的TransitionDrawable無法很好地處理不同寬高比的過渡問題,這的確是個(gè)Bug,是Android的也是Glide的。 解決辦法:使用.dontAnimate()方法禁用過渡動(dòng)畫,或者使用animate()方法自己寫動(dòng)畫,再或者自己修復(fù)TransitionDrawable的問題。
3、ImageView的資源回收問題 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 問題描述:默認(rèn)情況下,Glide會(huì)根據(jù)with()使用的Activity或Fragment的生命周期自動(dòng)調(diào)整資源請求以及資源回收。但是如果有很占內(nèi)存的Fragment或Activity不銷毀而僅僅是隱藏視圖,那么這些圖片資源就沒辦法及時(shí)回收,即使是GC的時(shí)候。 解決辦法:可以考慮使用WeakReference,如:? ? final WeakReferenceimageViewWeakReference = new WeakReference<>(imageView);
ImageView target = imageViewWeakReference.get();
if (target != null) {
Glide.with(context).load(uri).into(target);
}
4、ImageView的scaleType問題
scaleType默認(rèn)為fitCenter模式,如果你想設(shè)置成centerInside,不好意思,3.x還沒有這個(gè)方法,參見這個(gè)#591 issue,折中的解決辦法就是放棄使用centerInside,或者結(jié)合android:scaleType="centerInside"和.dontTransform()使用以禁止Glide對資源進(jìn)行轉(zhuǎn)換。
如果你想要ImageView的寬高根據(jù)圖片資源的大小而定(即使用wrap_comtent),那么你就必須明確告訴Glide我想加載原始資源:使用android:scaleType="center",或者.dontTransform(),或者.override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)。
不推薦使用fitXY,因?yàn)檫@樣Glide會(huì)加載全尺寸圖像到內(nèi)存中而造成不必要的內(nèi)存占用。
5、異步線程完成后加載圖片的崩潰問題
問題描述:通常情況下,異步線程會(huì)被約束在Activity生命周期內(nèi),所以異步線程完成后使用Glide加載圖片是沒有問題的。但如果你的異步線程在Activity銷毀時(shí)沒有取消掉,那么異步線程完成后就Glide就無法為一個(gè)已銷毀的Activity加載圖片資源,拋出的異常如下(在with()方法中就進(jìn)行判斷并拋出異常):
java.lang.IllegalArgumentException: You cannot start a load for a destroyed activity
at com.bumptech.glide.manager.RequestManagerRetriever.assertNotDestroyed(RequestManagerRetriever.java:134)
at com.bumptech.glide.manager.RequestManagerRetriever.get(RequestManagerRetriever.java:102)
at com.bumptech.glide.Glide.with(Glide.java:653)
at com.frank.glidedemo.TestActivity.onGetDataCompleted(TestActivity.java:23)
at com.frank.glidedemo.TestActivity.access$000(TestActivity.java:10)
at com.frank.glidedemo.TestActivity$BackgroundTask.onPostExecute(TestActivity.java:46)
at com.frank.glidedemo.TestActivity$BackgroundTask.onPostExecute(TestActivity.java:28)
at android.os.AsyncTask.finish(AsyncTask.java:632)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
}
解決辦法:正確管理Background Threads(異步線程),當(dāng)Activity停止或銷毀時(shí),停止所有相關(guān)的異步線程,停止所有后續(xù)的UI操作。或者加載前使用isFinishing()或isDestroyed()進(jìn)行限制(不建議這種處理方式)。
6、由于Bitmap復(fù)用導(dǎo)致的在某些設(shè)備上圖片錯(cuò)亂的問題
問題描述: Glide默認(rèn)使用BitmapPool的方式對應(yīng)用中用到的Bitmap進(jìn)行復(fù)用,以減少頻繁的內(nèi)存申請和內(nèi)存回收,而且默認(rèn)使用的Bitmap模式為RGB565以減少內(nèi)存開銷。但在某些設(shè)備上(通常在Galaxy系列5.X設(shè)備上很容易復(fù)現(xiàn))某些情況下會(huì)出現(xiàn)圖片加載錯(cuò)亂的問題,具體詳見這個(gè)#601 issue。原因初步確定是OpenGL紋理渲染異常。
解決辦法:GlideModule使用PREFER_ARGB_8888(Glide4.X已經(jīng)默認(rèn)使用該模式了),雖然內(nèi)存占用比RGB565更多一點(diǎn),但可以更好地處理有透明度Bitmap的復(fù)用問題?;蛘呓肂itmap復(fù)用setBitmapPool(new BitmapPoolAdapter())來修復(fù)這個(gè)問題(不推薦這種處理方式)
6、Picasso和Glide的區(qū)別
1、Glide比Picasso加載速度快
2、默認(rèn)情況Glide更有利于減少OutOfMemoryError的發(fā)生,不過Picasso的圖片質(zhì)量更高
3、Glide支持gif,Picasso不支持