by hzwusibo? 20190504
優(yōu)點:
支持gif
鏈式調用 (? 編程性強、? 可讀性強? 、 代碼簡潔)
glide三級緩存
Glide會自動判斷ImageView的大小,然后只將這么大的圖片像素加載到內存當中,幫助我們節(jié)省內存開支。
對象池的使用生命周期綁定:圖片的加載任務會與activity或者Fragment的生命周期綁定,當界面執(zhí)行onStop的使用自動暫定,而當執(zhí)行onStart的時候又會自動重新開啟,同樣的,動態(tài)Gif圖的加載也是如此,以用來節(jié)省電量,
同時Glide會對網絡狀態(tài)做監(jiān)聽,當網絡狀態(tài)發(fā)生改變時,會重啟失敗的任務,以減少任務因網絡連接問題而失敗的概率。
預覽圖的使用
Q1:看過Glide源碼嗎,你印象最深的是什么?
Glide的緩存設計非常先進,考慮的場景也很周全。在緩存上Glide 分成了兩個模塊,一個是內存緩存,一個是硬盤緩存。
這兩個緩存模塊的作用各不相同,內存緩存的主要作用是防止應用重復將圖片數據讀取到內存當中,而硬盤緩存的主要作用是防止應用重復從網絡或其他地方重復下載和讀取數據。
Q2:簡單說一下Glide的三級緩存?
Glide緩存機制大致分為三層:內存緩存、弱引用緩存、磁盤緩存。
存的順序是:弱引用、內存、磁盤
取的順序是:內存、弱引用、磁盤
Q3:?glide三級緩存,glide加載一個一兆的圖片(100*100),是否會壓縮后再加載,放到一個200*200的view上會怎樣,1000*1000呢,圖片會很模糊,怎么處理?
而使用Glide,我們不用擔心圖片內存浪費,內存溢出的問題。因為Glide不會直接將圖片的完整尺寸全部加載到內存中,而是用多少加載多少。Glide會自動判斷ImageView的大小,然后只將這么大的圖片像素加載到內存當中,幫助我們節(jié)省內存開支。
安卓圖片顯示的質量配置主要分為四種:
ARGB_8888 :32位圖,帶透明度,每個像素占4個字節(jié)
ARGB_4444 :16位圖,帶透明度,每個像素占2個字節(jié)
RGB_565 :16位圖,不帶透明度,每個像素占2個字節(jié)
ALPHA_8 :32位圖,只有透明度,不帶顏色,每個像素占4個字節(jié)
Glide的默認質量則為 RGB_565
Picasso的默認質量是 ARGB_8888?
Glide也并沒有使用什么神奇的魔法,它內部的實現原理其實就是insmaplesize技術,
Android高效加載大圖、多圖解決方案,有效避免程序OOM
https://blog.csdn.net/guolin_blog/article/details/9316683
inSampleSize優(yōu)化
http://m.itdecent.cn/p/f15cd2ed6ec0
一個可選的BitmapFactory.Options參數,將這個參數的inJustDecodeBounds屬性設置為true就可以讓解析方法禁止為bitmap分配內存,返回值也不再是一個Bitmap對象,而是null。雖然Bitmap是null了,但是BitmapFactory.Options的outWidth、outHeight和outMimeType屬性都會被賦值。
inSampleSize的默認值和最小值為1(當小于1時,解碼器將該值當做1來處理),且在大于1時,該值只能為2的冪(當不為2的冪時,解碼器會取與該值最接近的2的冪)。例如,當inSampleSize為2時,一個20001000的圖片,將被縮小為1000500,相應地,它的像素數和內存占用都被縮小為了原來的1/4:
Glide VS Picasso
不僅僅是 Google的推薦,支持 GIF 。 在沒有 Glide 之前,常用的做法就是寫了個自定義 view 然后 用一個 media 去播放。有了 Glide 之后可以像普通圖片那樣去加載并且顯示出來動圖。
Glide VS fresco
fresco 最大只支持圖片文件大小為 2M 。有時候大的時候,? Glide 正常顯示, fresco顯示黑屏。。。
fresco 更多是native實現。所以需要對NDK有所了解,,相比較于 Glide, 同樣遇到問題之后,修改源碼的成本,Glide 更方便。
Glide VS Android-Universal-Image-Loader
已經不再維護的開源庫,
Android碎片化那么嚴重,我們自己維護起來還是要考慮成本的。所以 Glide 勝出。?
Glide 支持功能更多。 比如 BitmapTransformation,比如圓形,圓角等。
更多變換
在圖片組件中我實現了三種自定義變換,包含圓形,圓角和模糊。
網上也有很多Glide的圖片變換開源庫,我感覺做的最好的是glide-transformations這個庫了吧。它實現了很多通用的圖片變換效果,如裁剪變換、顏色變換、模糊變換等等,使得我們可以非常輕松地進行各種各樣的圖片變換。不過我們用不到那么多功能的話也不需要依賴一個三方庫了吧,主要還是要學習為主。
Glide 是如何解決圖片加載生命周期的?
Glide 的使用方式上,一定需要傳入一個 context 給它??梢愿鶕煌纳舷挛倪M行處理,拿到 context (除了application context)之后,Glide做了一件很巧妙的事情,就是在這個界面上追加一個 fragment,由于 fragment 添加到了 activity 上,是可以捕獲到生命周期的,因此可以在 destroy 的時候取消掉當前context下的 glide對象中的加載任務。
Glide 坑爹的 wrap_content 不支持的問題
官方說了的,不支持并且不建議imageview設置wrap_content。因為這樣 glide 不知道要加載多大的圖片給我們才好。? 普通的imageview其實也還好,如果放在列表(RecyclerView)中,? 由于我們并不知道目標圖片大小是多大的,所以我們選擇了wrap_content,那么在上下來回滾動過程中,就會導致圖片一會大一會小的bug.
Glide Module自定義緩存
圖片框架中很多自定義的實現,而緩存也是框架中最為常見的行為之一。因此在開發(fā)使用中有些項目需求不凡試下自定義Glide的緩存.
https://blog.csdn.net/qq_38859786/article/details/80291476
源碼解析
1,Glide采用的是三級緩存,內存–>磁盤–>網絡
Glide的緩存功能,大部分都是在load()方法中進行的
?A:內存緩存的主要作用 :??? 是防止應用重復將圖片數據讀取到內存當中,
?B:磁盤緩存的主要作用 :?? 是防止應用重復從網絡或其他地方重復下載和讀取數據。
?C:Glide內存緩存的實現使用的LruCache算法。結合弱引用的機制,共同完成了內存緩存功能
3,Glide.with()
?????With方法有5個重載的構造方法,運行你在activity,frgament或者其他地方使用.得到一個RequestManager對象 ,RequestManager實現了LifeCycleListener接口,綁定Activity/Fragment生命周期,對請求進行暫停,恢復,清除操作.
下面是5個構造方法
//RequestManager實現了LifeCycleListener接口
public static RequestManager with(Context context) {
? ? RequestManagerRetriever retriever = RequestManagerRetriever.get();
? ? return retriever.get(context);
}
public static RequestManager with(Activity activity) {
? ? RequestManagerRetriever retriever = RequestManagerRetriever.get();
? ? return retriever.get(activity);
}
public static RequestManager with(FragmentActivity activity) {
? ? RequestManagerRetriever retriever = RequestManagerRetriever.get();
? ? return retriever.get(activity);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static RequestManager with(android.app.Fragment fragment) {
? ? RequestManagerRetriever retriever = RequestManagerRetriever.get();
? ? return retriever.get(fragment);
}
//V4包的fragment
public static RequestManager with(Fragment fragment) {
? ? RequestManagerRetriever retriever = RequestManagerRetriever.get();
? ? return retriever.get(fragment);
}
3.1RequestManage對象源碼
public class RequestManager implements LifecycleListener {
? ? private final Context context;
? ? private final Lifecycle lifecycle;
? ? private final RequestManagerTreeNode treeNode;
? ? private final RequestTracker requestTracker;
? ? private final Glide glide;
? ? public RequestManager(Context context, Lifecycle lifecycle, RequestManagerTreeNode treeNode) {
? ? ? ? this(context, lifecycle, treeNode, new RequestTracker(), new ConnectivityMonitorFactory());
? ? }
? ? RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,
? ? ? ? ? ? ? ? ? RequestTracker requestTracker, ConnectivityMonitorFactory factory) {
? ? ? ? this.context = context.getApplicationContext();
? ? ? ? this.lifecycle = lifecycle;
? ? ? ? this.treeNode = treeNode;
? ? ? ? this.requestTracker = requestTracker;
? ? ? ? //通過Glide的靜態(tài)方法獲取實例對象,Glide是通過單利創(chuàng)建的
? ? this.glide = Glide.get(context);
? ? ? ? this.optionsApplier = new OptionsApplier();
4,load(url)
Glide的緩存功能,大部分都是在load()方法中進行的
load()也有很多重載的方法,它可以加載網絡圖片,本地圖片,gif(動態(tài)圖)圖,Uri,File,
public DrawableTypeRequest<String> load(String string) {
? ? return (DrawableTypeRequest<String>) fromString().load(string);
}
//加載Uri
public DrawableTypeRequest<Uri> load(Uri uri) {
? ? return (DrawableTypeRequest<Uri>) fromUri().load(uri);
}
//加載File
public DrawableTypeRequest<File> load(File file) {
? ? return (DrawableTypeRequest<File>) fromFile().load(file);
}
//直接加載圖片資源id,? R.mipmap.ic_launcher
public DrawableTypeRequest<Integer> load(Integer resourceId) {
? ? return (DrawableTypeRequest<Integer>) fromResource().load(resourceId);
}
//加載URL
@Deprecated
public DrawableTypeRequest<URL> load(URL url) {
? ? return (DrawableTypeRequest<URL>) fromUrl().load(url);
}
5,Glide的into()方法
public Target<TranscodeType> into(ImageView view) {
? ? Util.assertMainThread();
? ? if (view == null) {
? ? ? ? throw new IllegalArgumentException("You must pass in a non null View");
? ? }
? ? if (!isTransformationSet && view.getScaleType() != null) {
? ? ? ? switch (view.getScaleType()) {
? ? ? ? ? ? case CENTER_CROP:
? ? ? ? ? ? ? ? applyCenterCrop();
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case FIT_CENTER:
? ? ? ? ? ? case FIT_START:
? ? ? ? ? ? case FIT_END:
? ? ? ? ? ? ? ? applyFitCenter();
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? //$CASES-OMITTED$
? ? ? ? ? ? default:
? ? ? ? ? ? ? ? // Do nothing.
? ? ? ? }
? ? }
? ? return into(glide.buildImageViewTarget(view, transcodeClass));
}
最終調用的into方法
//Target我們可以理解成View,只是Glide對我們的View做了一層封裝。
public <Y extends Target<TranscodeType>> Y into(Y target) {
? ? //判斷是否在主線程,(UI界面更新只能在主線程),不在主線程就報異常
? ? Util.assertMainThread();
? ? if (target == null) {
? ? ? ? throw new IllegalArgumentException("You must pass in a non null Target");
? ? }
? ? if (!isModelSet) {
? ? ? ? throw new IllegalArgumentException("You must first set a model (try #load())");
? ? }
? ? //獲取request對象
? ? Request previous = target.getRequest();
? ? //requestTracker是請求跟蹤類對象,主要管理請求的發(fā)起,暫停,清除
? ? if (previous != null) {
? ? ? ? previous.clear();
? ? ? ? requestTracker.removeRequest(previous);
? ? ? ? previous.recycle();
? ? }
? ? //創(chuàng)建request對象
? ? Request request = buildRequest(target);
? ? target.setRequest(request);
? ? //將target加入lifecycle,綁定生命周期
? ? lifecycle.addListener(target);
? ? //執(zhí)行請求
? ? requestTracker.runRequest(request);
? ? return target;
Android圖片加載框架最全解析(一),Glide的基本用法
https://blog.csdn.net/guolin_blog/article/details/53759439
Android圖片加載框架最全解析(二),從源碼的角度理解Glide的執(zhí)行流https://blog.csdn.net/guolin_blog/article/details/53939176
Android圖片加載框架最全解析(五),Glide強大的圖片變換功能
https://blog.csdn.net/guolin_blog/article/details/71524668
Android圖片加載框架最全解析(七),實現帶進度的Glide圖片加載功能
https://blog.csdn.net/guolin_blog/article/details/78357251
磁盤緩存
//DiskCacheStrategy.SOURCE:緩存原始數據,
// DiskCacheStrategy.RESULT:緩存變換后的資源數據,
// DiskCacheStrategy.NONE:什么都不緩存,
DiskCacheStrategy.ALL:緩存SOURC和RESULT。
? // 默認采用DiskCacheStrategy.RESULT策略
Glide會為每種大小的ImageView緩存一次。盡管一張圖片已經緩存了一次,但是假如你要在另外一個地方再次以不同尺寸顯示,需要重新下載,調整成新尺寸的大小,然后將這個尺寸的也緩存起來。具體說來就是:假如在第一個頁面有一個200x200的ImageView,在第二個頁面有一個100x100的ImageView,這兩個ImageView本來是要顯示同一張圖片,卻需要下載兩次;可以通過改變Glide的行為讓它即加載全尺寸圖片,也加載不同尺寸圖片
Glide.with(this)?
.load("http://nuuneoi.com/uploads/source/playstore/cover.jpg")?
.diskCacheStrategy(DiskCacheStrategy.ALL)?
.into(ivImgGlide);?
下次在任何ImageView中加載圖片的時候,全尺寸的圖片將從緩存中取出,重新調整大小,然后緩存。