圖片加載要考慮的問題
圖片加載不僅僅是將圖片顯示出來的問題,不同場景該使用什麼縮放模式?activity銷燬後圖片還在後臺請求?是否會造成內存浪費?設置佔位符和加載失敗的圖片?圓角圖等怎麼變換?
讀郭霖Glide圖片加載框架總結
帶着以上問題,拜讀了郭霖大神的Glide圖片加載框,總結並實際驗證,得出以下幾點:
1.圖片加載週期
Glide最簡單的用法:
Glide.with(context).load(url).into(imageView)
with()方法中傳入的Context實例會決定Glide加載圖片的生命週期,如果傳入的是Activity或者Fragment的實例,那麼當這個Activity或Fragment被銷燬的時候,圖片加載也會停止。如果傳入的是ApplicationContext,那麼只有當應用程序被殺掉的時候,圖片加載纔會停止。
想法:傳入ImageView.getContext()實例是不是最好的方案,ImageView所在的Context銷燬了,圖片自然應該取消加載。此方案是否可行?列表的回收機制會不會有問題?
結論:不是最好的方案,fragment和adapter中ImageView.getContext()返回的都是Activity,當fragment或adapter銷燬但activity並沒有銷燬時,圖片仍會加載,所以生命週期並不合理
2.圖片格式(Bitmap,Gif)
Glide是支持加載GIF圖片的,不需要編寫額外的代碼,Glide內部會自動判斷圖片格式(Gif圖不一定是以.gif後綴結尾的哦。
當然也可以手動指定圖片格式:
調用了asBitmap()方法,靜態圖正常加載,GIF圖無法正常播放,會在界面上顯示第一幀的圖片;
調用了asGif()方法,GIF圖正常加載和播放,靜態圖加載失敗。
想法:一般情況下不需要指定圖片格式,動圖的播放機制(一直循環播放/只播放一次)怎麼設置?默認是循環播放
結論:設置監聽,回調中設置播放次數,如下:
Glide.with(this)
.load(url)
.addListener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(
@Nullable GlideException e, Object model,
Target<Drawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(Drawable resource,
Object model, Target<Drawable> target,
DataSource dataSource,
boolean isFirstResource) {
if (resource instanceof GifDrawable) {
//設置播放次數
((GifDrawable) resource).setLoopCount(3);
}
return false;
}
})
.into(iv);
緩存
在緩存這一功能上,Glide又將它分成了兩個模塊,一個是內存緩存,一個是硬盤緩存。
默認情況下,Glide自動就是開啓內存緩存和磁盤緩存的。
磁盤緩存是存在哪的?是否需要動態權限,未授權時磁盤緩存是不是就失效了?
結論:磁盤緩存默認存儲在應用內部文件,訪問應用內部文件無需動態申請權限
集成網絡框架
Glide默認使用的是HttpUrlConnection,支持集成Volley,Okhttp等其它網絡棧。
想法:一般用的時候沒有集成過網絡棧,如何集成?
權限
一般使用場景是加載網絡圖片,Internet權限肯定是要的,但還有個小細節:如果你正在從 URL 加載圖片,Glide 可以自動幫助你處理片狀網絡連接:它可以監聽用戶的連接狀態並在用戶重新連接到網絡時重啓之前失敗的請求。如果 Glide 檢測到你的應用擁有 ACCESS_NETWORK_STATE 權限,Glide 將自動監聽連接狀態而不需要額外的改動。
佔位符
placeHolder
error
fallback
佔位圖是否會影響控件的大小?
結論:不會,網上有人說會有問題,我用的Glide4.9版本試的,可能Glide已經修復了
淡入效果
transitionOption
變換
縮放模式適配不同場景:
啓動頁/廣告頁
全屏展示(填充寬高),不變形,儘可能少的裁剪內容[我特地問了做設計的朋友,他們是有設計規範的,四周不會放內容,xx像素內是內容區域。所以適當的裁剪掉邊上的內容是沒有問題的]。使用centerCrop就可滿足上述條件。
banner
banner一般都是以ViewPager做容器,ViewPager的高度是不支持wrap_content的,也就是說要麼指定高度,要麼match_parent。banner的寬一般是固定的,高度若是寫死,採用fitXY在有些手機上會有變形;fitCenter周邊可能會有留白;centerCrop又會裁剪掉邊上的內容 (banner一般要求不能裁剪,本來區域就不大,你還裁剪,可能會丟失重要內容)。
寬固定,高根據圖片比例算出控件高,設置給ViewPager,因爲viewPager會預加載兩邊的view,所以適配的前提是所有banner圖片寬高比一致(一般都能滿足)
Glide.with(context)
.load(url)
.addListener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
//根據圖片寬高比設置容器的高度
int intrinsicWidth = resource.getIntrinsicWidth();
int intrinsicHeight = resource.getIntrinsicHeight();
int height = intrinsicHeight * width / intrinsicWidth;
layoutParams.height = height;
return false;
}
})
.override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.transform(new RoundedCorners(10))
.into(imageView);
固定寬高
圖片不變形,不裁剪,fitCenter即可滿足。
圓角
RoundedCorners
圓形
CircleCrop
不得不說Glide的設計真的滿足了我們99%的場景需求了。