與其他圖片加載庫相同,Glide除了可以加載網(wǎng)絡(luò)圖片之外,也可以加載本地圖片。甚至還可以從各種各樣奇葩的數(shù)據(jù)源中加載圖片。
加載網(wǎng)絡(luò)圖片
很多情況下,我們使用圖片加載庫就是為了加載網(wǎng)絡(luò)圖片。網(wǎng)絡(luò)操作是一個很復(fù)雜的東西。試想一下,如果沒有圖片加載庫,我們就要手動去下載圖片,緩存圖片,最后再從文件里面讀取bitmap并設(shè)置到Imageview里面。這還算好的,要是在Listview里面你會更頭疼的。原因我就不說了,你懂的~~再加上各種各樣的Bitmap操作,保準(zhǔn)你再也不想擼代碼了。而且Bitmap這東西還很占內(nèi)存,伺候不好,很容易就會引發(fā)OOM,app吧唧就閃退了??!
圖片加載庫的優(yōu)勢就在于此。簡簡單單一句話,下載,緩存,加載統(tǒng)統(tǒng)搞定。簡直就是美好一生的東西。而Glide就是這樣使人美好一生的東西之一。
說了這么多,Glide如何加載網(wǎng)絡(luò)圖片?很簡單,就上次的三句話:
ImageView targetImageView = (ImageView) findViewById(R.id.imageView);
String internetUrl = "http://i.imgur.com/idojSYm.png";
Glide
.with(context)
.load(internetUrl)
.into(targetImageView);
木有什么亂七八糟的東西,直接傳入要加載圖片的url就可以了。那么圖片加載庫有很多,為什么選擇Glide呢?很簡單,因為它流暢,不卡,尤其是在Listview中。嗯,就是醬~
加載本地圖片
下表是.load()可以傳入的參數(shù)及說明
| 參數(shù) | 說明 |
|---|---|
| .load(String string) | string可以為一個文件路徑、uri或者url |
| .load(Uri uri) | uri類型 |
| .load(File file) | 文件 |
| .load(Integer resourceId) | 資源Id,R.drawable.xxx或者R.mipmap.xxx |
| .load(byte[] model) | byte[]類型 |
| .load(T model) | 自定義類型 |
從上面可以看到Glide不僅可以加載網(wǎng)絡(luò)圖片,還可以加載本地圖片??山邮艿膮?shù)有文件路徑,uri,文件,資源id等?;旧蠞M足了大部分的需求。雖然加載本地圖片不像網(wǎng)絡(luò)圖片那樣復(fù)雜,但我還是建議使用Glide來加載本地圖片。因為它是內(nèi)存友好的,而且還會“偷偷地”幫我們做很多事情。比如內(nèi)存緩存,Bitmap復(fù)用,修正照片方向等。當(dāng)然為了滿足各種各樣的需求,僅僅加載圖片是不夠的,你還需要對圖片進(jìn)行各種各樣的變換,也就是Transformation。后面我們會詳細(xì)了解的。
加載自定義數(shù)據(jù)源
前面的表格中有一個是我們不熟悉的,就是.load(T model),即自定義的數(shù)據(jù)源類型。那么如何去實現(xiàn)呢?
實際上,加載自定義數(shù)據(jù)源主要是通過ModelLoader接口來實現(xiàn)的。由于沒有在實際項目中用到過,這方面的經(jīng)驗比較少。想深入了解的,可以參考這篇文章。
不過從官方Wiki上來看,設(shè)計ModelLoader接口的初衷用來加載不同尺寸的圖片的。眾所周知,Android設(shè)備屏幕分辨率千奇百怪,大到2K,小到320p。如果在低分辨率的手機(jī)上加載大圖,不僅損耗用戶流量,而且很容易造成OOM;在高分辨的手機(jī)上,加載小圖又會出現(xiàn)模糊的情況,用戶體驗極差。很多時候,為了省事,很多app都會選擇一個中間分辨率,然后自適應(yīng)大小。當(dāng)然這樣做無可厚非,但是有更好的辦法,我們?yōu)槭裁床蝗L試呢?
那么如何使用Glide來實現(xiàn)這一具體需求呢?首先你要實現(xiàn)自己的ModelLoader,比較簡單的方法是繼承BaseGlideUrlLoader。
public interface MyDataModel {
public String buildUrl(int width, int height);
}
public class MyUrlLoader extends BaseGlideUrlLoader<MyDataModel> {
@Override
protected String getUrl(MyDataModel model, int width, int height) {
// Construct the url for the correct size here.
return model.buildUrl(width, height);
}
}
接下來我們可以這樣來加載圖片:
Glide.with(this)
.using(new MyUrlLoader(this))
.load(new MyDataModel() {
@Override
public String buidUrl(int width, int height) {
if (width >= 600) {
return url1;
} else {
return url2;
}
}
})
.into(imageView);
.using(new MyUrlLoader(this)):使用我們自己的ModeLoader;
.load(new MyDataModel()):加載我們自定義的數(shù)據(jù)源
這里需要解釋下getUrl的三個參數(shù):
model:你加載的數(shù)據(jù)源
width:你加載的圖片的寬度(px)
height:你加載的圖片的高度(px)
這樣,我們在高分率的設(shè)備上加載大圖的url1,在低分辨率的設(shè)備上加載小圖url2。從而實現(xiàn)了根據(jù)不同手機(jī)上的像素值大小加載不同尺寸的圖片的需求。
當(dāng)然如果你不想每次都是用.using(new MyUrlLoader()),就需要實現(xiàn)一個自定義的ModelLoaderFactory并在GlideModule中注冊。
public class MyGlideModule implements GlideModule {
...
@Override
public void registerComponents(Context context, Glide glide) {
glide.register(MyDataModel.class, InputStream.class,
new MyUrlLoader.Factory());
}
}
同時也要在AndroidManifest.xml聲明
<meta-data
android:name="com.mypackage.MyGlideModule"
android:value="GlideModule" />
如果你有多個自定義的GlideModule類,那么也要在AndroidManifest.xml中聲明多個GlideModule。
對于上面的加載不同尺寸的圖片,Google的2014年I/O大會App中有一篇文章專門用來介紹這個的,地址在這里。大概原理是這樣子的:
在服務(wù)端有下面的幾個可以加載的url:
| URL | 圖片大小 |
|---|---|
| myserver.com/images/__w-200-400-600-800-1000__/session1.jpg | 原始尺寸 |
| myserver.com/images/w200/session1.jpg | 200px |
| myserver.com/images/w400/session1.jpg | 400px |
| myserver.com/images/w600/session1.jpg | 600px |
| myserver.com/images/w800/session1.jpg | 800px |
| myserver.com/images/w1000/session1.jpg | 1000px |
那么客戶端如何根據(jù)不同的手機(jī)分辨率去加載不同的url呢?
Google是這樣做的,下面是核心代碼:
//定義正則表達(dá)式
private static final Pattern PATTERN =
Pattern.compile("__w-((?:-?\\d+)+)__");
@Override
protected String getUrl(String model, int width, int height) {
Matcher m = PATTERN.matcher(model);
int bestBucket = 0;
if (m.find()) {
String[] found = m.group(1).split("-");//拿到可以加載的尺寸數(shù)組
for (String bucketStr : found) {
bestBucket = Integer.parseInt(bucketStr);
if (bestBucket >= width) {//剛好大于要加載的尺寸,直接跳出循環(huán)
// the best bucket is the first immediately
// bigger than the requested width
break;
}
}
if (bestBucket > 0) {//返回合適尺寸的url
model = m.replaceFirst("w"+bestBucket);
}
}
return model;
}
大概的步驟如下:
1.根據(jù)服務(wù)端可加載的圖片url定義正則表達(dá)式
2.根據(jù)正則匹配,獲取到可以加載的圖片尺寸數(shù)組
3.根據(jù)要加載的Imageview的大小,選擇合適的尺寸的url
4.拼接url并返回
上面的例子中有200,400,600,800,1000是可以加載的,如果你要加載的Imageview的大小為600px,當(dāng)遍歷數(shù)組到600時,就會直接跳出循環(huán),返回600px大小圖片的url,Glide就會加載600px的圖片。
最后送上一個小demo:https://github.com/Alluretears/GldieDemo