Gilde小結(jié)

by hzwusibo? 20190504


優(yōu)點(diǎn):

支持gif

鏈?zhǔn)秸{(diào)用 (? 編程性強(qiáng)扩所、? 可讀性強(qiáng)? 围详、 代碼簡潔)

glide三級(jí)緩存

Glide會(huì)自動(dòng)判斷ImageView的大小,然后只將這么大的圖片像素加載到內(nèi)存當(dāng)中祖屏,幫助我們節(jié)省內(nèi)存開支助赞。

對(duì)象池的使用生命周期綁定:圖片的加載任務(wù)會(huì)與activity或者Fragment的生命周期綁定,當(dāng)界面執(zhí)行onStop的使用自動(dòng)暫定袁勺,而當(dāng)執(zhí)行onStart的時(shí)候又會(huì)自動(dòng)重新開啟雹食,同樣的,動(dòng)態(tài)Gif圖的加載也是如此期丰,以用來節(jié)省電量群叶,

同時(shí)Glide會(huì)對(duì)網(wǎng)絡(luò)狀態(tài)做監(jiān)聽吃挑,當(dāng)網(wǎng)絡(luò)狀態(tài)發(fā)生改變時(shí),會(huì)重啟失敗的任務(wù)街立,以減少任務(wù)因網(wǎng)絡(luò)連接問題而失敗的概率舶衬。

預(yù)覽圖的使用

Q1:看過Glide源碼嗎,你印象最深的是什么赎离?

Glide的緩存設(shè)計(jì)非常先進(jìn)逛犹,考慮的場(chǎng)景也很周全。在緩存上Glide 分成了兩個(gè)模塊梁剔,一個(gè)是內(nèi)存緩存虽画,一個(gè)是硬盤緩存。

這兩個(gè)緩存模塊的作用各不相同荣病,內(nèi)存緩存的主要作用是防止應(yīng)用重復(fù)將圖片數(shù)據(jù)讀取到內(nèi)存當(dāng)中码撰,而硬盤緩存的主要作用是防止應(yīng)用重復(fù)從網(wǎng)絡(luò)或其他地方重復(fù)下載和讀取數(shù)據(jù)。

Q2:簡單說一下Glide的三級(jí)緩存个盆?

Glide緩存機(jī)制大致分為三層:內(nèi)存緩存灸拍、弱引用緩存、磁盤緩存砾省。

存的順序是:弱引用、內(nèi)存混槐、磁盤

取的順序是:內(nèi)存编兄、弱引用、磁盤

Q3:?glide三級(jí)緩存声登,glide加載一個(gè)一兆的圖片(100*100)狠鸳,是否會(huì)壓縮后再加載,放到一個(gè)200*200的view上會(huì)怎樣悯嗓,1000*1000呢件舵,圖片會(huì)很模糊,怎么處理脯厨?

而使用Glide铅祸,我們不用擔(dān)心圖片內(nèi)存浪費(fèi),內(nèi)存溢出的問題合武。因?yàn)镚lide不會(huì)直接將圖片的完整尺寸全部加載到內(nèi)存中临梗,而是用多少加載多少。Glide會(huì)自動(dòng)判斷ImageView的大小稼跳,然后只將這么大的圖片像素加載到內(nèi)存當(dāng)中盟庞,幫助我們節(jié)省內(nèi)存開支。

安卓圖片顯示的質(zhì)量配置主要分為四種:

ARGB_8888 :32位圖,帶透明度,每個(gè)像素占4個(gè)字節(jié)

ARGB_4444 :16位圖,帶透明度,每個(gè)像素占2個(gè)字節(jié)

RGB_565 :16位圖,不帶透明度,每個(gè)像素占2個(gè)字節(jié)

ALPHA_8 :32位圖,只有透明度,不帶顏色,每個(gè)像素占4個(gè)字節(jié)

Glide的默認(rèn)質(zhì)量則為 RGB_565

Picasso的默認(rèn)質(zhì)量是 ARGB_8888?

Glide也并沒有使用什么神奇的魔法汤善,它內(nèi)部的實(shí)現(xiàn)原理其實(shí)就是insmaplesize技術(shù)什猖,

Android高效加載大圖票彪、多圖解決方案,有效避免程序OOM

https://blog.csdn.net/guolin_blog/article/details/9316683

inSampleSize優(yōu)化

http://www.reibang.com/p/f15cd2ed6ec0

一個(gè)可選的BitmapFactory.Options參數(shù)不狮,將這個(gè)參數(shù)的inJustDecodeBounds屬性設(shè)置為true就可以讓解析方法禁止為bitmap分配內(nèi)存降铸,返回值也不再是一個(gè)Bitmap對(duì)象,而是null荤傲。雖然Bitmap是null了垮耳,但是BitmapFactory.Options的outWidth、outHeight和outMimeType屬性都會(huì)被賦值遂黍。

inSampleSize的默認(rèn)值和最小值為1(當(dāng)小于1時(shí)终佛,解碼器將該值當(dāng)做1來處理),且在大于1時(shí)雾家,該值只能為2的冪(當(dāng)不為2的冪時(shí)铃彰,解碼器會(huì)取與該值最接近的2的冪)。例如芯咧,當(dāng)inSampleSize為2時(shí)牙捉,一個(gè)20001000的圖片,將被縮小為1000500敬飒,相應(yīng)地邪铲,它的像素?cái)?shù)和內(nèi)存占用都被縮小為了原來的1/4:

Glide VS Picasso

不僅僅是 Google的推薦,支持 GIF 无拗。 在沒有 Glide 之前带到,常用的做法就是寫了個(gè)自定義 view 然后 用一個(gè) media 去播放。有了 Glide 之后可以像普通圖片那樣去加載并且顯示出來動(dòng)圖英染。

Glide VS fresco

fresco 最大只支持圖片文件大小為 2M 揽惹。有時(shí)候大的時(shí)候,? Glide 正常顯示四康, fresco顯示黑屏搪搏。。闪金。

fresco 更多是native實(shí)現(xiàn)疯溺。所以需要對(duì)NDK有所了解,哎垦,相比較于 Glide喝检, 同樣遇到問題之后,修改源碼的成本撼泛,Glide 更方便挠说。

Glide VS Android-Universal-Image-Loader

已經(jīng)不再維護(hù)的開源庫,

Android碎片化那么嚴(yán)重愿题,我們自己維護(hù)起來還是要考慮成本的损俭。所以 Glide 勝出蛙奖。?

Glide 支持功能更多。 比如 BitmapTransformation杆兵,比如圓形雁仲,圓角等。

更多變換

在圖片組件中我實(shí)現(xiàn)了三種自定義變換琐脏,包含圓形攒砖,圓角和模糊。

網(wǎng)上也有很多Glide的圖片變換開源庫日裙,我感覺做的最好的是glide-transformations這個(gè)庫了吧吹艇。它實(shí)現(xiàn)了很多通用的圖片變換效果,如裁剪變換昂拂、顏色變換受神、模糊變換等等,使得我們可以非常輕松地進(jìn)行各種各樣的圖片變換格侯。不過我們用不到那么多功能的話也不需要依賴一個(gè)三方庫了吧鼻听,主要還是要學(xué)習(xí)為主。

Glide 是如何解決圖片加載生命周期的联四?

Glide 的使用方式上撑碴,一定需要傳入一個(gè) context 給它〕眨可以根據(jù)不同的上下文進(jìn)行處理灰羽,拿到 context (除了application context)之后,Glide做了一件很巧妙的事情鱼辙,就是在這個(gè)界面上追加一個(gè) fragment,由于 fragment 添加到了 activity 上玫镐,是可以捕獲到生命周期的倒戏,因此可以在 destroy 的時(shí)候取消掉當(dāng)前context下的 glide對(duì)象中的加載任務(wù)。

Glide 坑爹的 wrap_content 不支持的問題

官方說了的恐似,不支持并且不建議imageview設(shè)置wrap_content杜跷。因?yàn)檫@樣 glide 不知道要加載多大的圖片給我們才好。? 普通的imageview其實(shí)也還好矫夷,如果放在列表(RecyclerView)中,? 由于我們并不知道目標(biāo)圖片大小是多大的葛闷,所以我們選擇了wrap_content,那么在上下來回滾動(dòng)過程中双藕,就會(huì)導(dǎo)致圖片一會(huì)大一會(huì)小的bug.

Glide Module自定義緩存

圖片框架中很多自定義的實(shí)現(xiàn),而緩存也是框架中最為常見的行為之一淑趾。因此在開發(fā)使用中有些項(xiàng)目需求不凡試下自定義Glide的緩存.

https://blog.csdn.net/qq_38859786/article/details/80291476

源碼解析

1,Glide采用的是三級(jí)緩存,內(nèi)存–>磁盤–>網(wǎng)絡(luò)

Glide的緩存功能,大部分都是在load()方法中進(jìn)行的

?A:內(nèi)存緩存的主要作用 :??? 是防止應(yīng)用重復(fù)將圖片數(shù)據(jù)讀取到內(nèi)存當(dāng)中,

?B:磁盤緩存的主要作用 :?? 是防止應(yīng)用重復(fù)從網(wǎng)絡(luò)或其他地方重復(fù)下載和讀取數(shù)據(jù)忧陪。

?C:Glide內(nèi)存緩存的實(shí)現(xiàn)使用的LruCache算法扣泊。結(jié)合弱引用的機(jī)制近范,共同完成了內(nèi)存緩存功能

3,Glide.with()

?????With方法有5個(gè)重載的構(gòu)造方法,運(yùn)行你在activity,frgament或者其他地方使用.得到一個(gè)RequestManager對(duì)象 ,RequestManager實(shí)現(xiàn)了LifeCycleListener接口,綁定Activity/Fragment生命周期延蟹,對(duì)請(qǐng)求進(jìn)行暫停评矩,恢復(fù),清除操作.

下面是5個(gè)構(gòu)造方法

//RequestManager實(shí)現(xiàn)了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對(duì)象源碼

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)方法獲取實(shí)例對(duì)象,Glide是通過單利創(chuàng)建的

? ? this.glide = Glide.get(context);

? ? ? ? this.optionsApplier = new OptionsApplier();



4,load(url)

Glide的緩存功能,大部分都是在load()方法中進(jìn)行的

load()也有很多重載的方法,它可以加載網(wǎng)絡(luò)圖片,本地圖片,gif(動(dòng)態(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));

}

最終調(diào)用的into方法

//Target我們可以理解成View,只是Glide對(duì)我們的View做了一層封裝阱飘。

public <Y extends Target<TranscodeType>> Y into(Y target) {

? ? //判斷是否在主線程,(UI界面更新只能在主線程),不在主線程就報(bào)異常

? ? 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對(duì)象

? ? Request previous = target.getRequest();

? ? //requestTracker是請(qǐng)求跟蹤類對(duì)象斥杜,主要管理請(qǐng)求的發(fā)起,暫停沥匈,清除

? ? if (previous != null) {

? ? ? ? previous.clear();

? ? ? ? requestTracker.removeRequest(previous);

? ? ? ? previous.recycle();

? ? }

? ? //創(chuàng)建request對(duì)象

? ? Request request = buildRequest(target);

? ? target.setRequest(request);

? ? //將target加入lifecycle,綁定生命周期

? ? lifecycle.addListener(target);

? ? //執(zhí)行請(qǐng)求

? ? 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強(qiáng)大的圖片變換功能

https://blog.csdn.net/guolin_blog/article/details/71524668

Android圖片加載框架最全解析(七)弱恒,實(shí)現(xiàn)帶進(jìn)度的Glide圖片加載功能

https://blog.csdn.net/guolin_blog/article/details/78357251

磁盤緩存

//DiskCacheStrategy.SOURCE:緩存原始數(shù)據(jù),

// DiskCacheStrategy.RESULT:緩存變換后的資源數(shù)據(jù)棋恼,

// DiskCacheStrategy.NONE:什么都不緩存返弹,

DiskCacheStrategy.ALL:緩存SOURC和RESULT。

? // 默認(rèn)采用DiskCacheStrategy.RESULT策略

Glide會(huì)為每種大小的ImageView緩存一次爪飘。盡管一張圖片已經(jīng)緩存了一次义起,但是假如你要在另外一個(gè)地方再次以不同尺寸顯示,需要重新下載师崎,調(diào)整成新尺寸的大小默终,然后將這個(gè)尺寸的也緩存起來。具體說來就是:假如在第一個(gè)頁面有一個(gè)200x200的ImageView犁罩,在第二個(gè)頁面有一個(gè)100x100的ImageView齐蔽,這兩個(gè)ImageView本來是要顯示同一張圖片,卻需要下載兩次;可以通過改變Glide的行為讓它即加載全尺寸圖片,也加載不同尺寸圖片

Glide.with(this)?

.load("http://nuuneoi.com/uploads/source/playstore/cover.jpg")?

.diskCacheStrategy(DiskCacheStrategy.ALL)?

.into(ivImgGlide);?

下次在任何ImageView中加載圖片的時(shí)候床估,全尺寸的圖片將從緩存中取出含滴,重新調(diào)整大小,然后緩存丐巫。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谈况,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子递胧,更是在濱河造成了極大的恐慌碑韵,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缎脾,死亡現(xiàn)場(chǎng)離奇詭異祝闻,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)遗菠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門治筒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來屉栓,“玉大人,你說我怎么就攤上這事耸袜∮讯啵” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵堤框,是天一觀的道長域滥。 經(jīng)常有香客問我,道長蜈抓,這世上最難降的妖魔是什么启绰? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮沟使,結(jié)果婚禮上委可,老公的妹妹穿的比我還像新娘宫峦。我一直安慰自己险领,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布劲绪。 她就那樣靜靜地躺著燕少,像睡著了一般卡者。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上客们,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天崇决,我揣著相機(jī)與錄音,去河邊找鬼底挫。 笑死恒傻,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的建邓。 我是一名探鬼主播盈厘,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼涝缝!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起譬重,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤拒逮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后臀规,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體滩援,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年塔嬉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了玩徊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片租悄。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖恩袱,靈堂內(nèi)的尸體忽然破棺而出泣棋,到底是詐尸還是另有隱情,我是刑警寧澤畔塔,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布潭辈,位于F島的核電站,受9級(jí)特大地震影響澈吨,放射性物質(zhì)發(fā)生泄漏把敢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一谅辣、第九天 我趴在偏房一處隱蔽的房頂上張望修赞。 院中可真熱鬧,春花似錦桑阶、人聲如沸柏副。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽搓扯。三九已至,卻和暖如春包归,著一層夾襖步出監(jiān)牢的瞬間锨推,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國打工公壤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留换可,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓厦幅,卻偏偏與公主長得像沾鳄,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子确憨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容