android ListView顯示網(wǎng)絡(luò)圖片
android ListView顯示網(wǎng)絡(luò)圖片
研究了android兩個(gè)禮拜,稍微有了點(diǎn)眉目,開(kāi)始正式幫公司開(kāi)發(fā)應(yīng)用的時(shí)候,發(fā)現(xiàn)ListView沒(méi)有現(xiàn)成的顯示網(wǎng)絡(luò)圖片的類或方法,網(wǎng)上查了查也沒(méi)找到好的解決方法。心一橫,自己研究吧,現(xiàn)在把我的解決辦法和大家分享一下。
使用ListView的方法就不在此介紹了,google一下都是的。
第一步:分析api
使用ListView都需要使用Adapter,而api中的adapter都繼承自BaseAdapter,所以第一反應(yīng)就是自己實(shí)現(xiàn)一個(gè)繼承自
BaseAdapter的adapter,但是BaseAdapter還是屬于高度抽象的基類,所以實(shí)現(xiàn)起來(lái)還是還是有點(diǎn)難度的。此時(shí)作為初學(xué)者的你(當(dāng)
然我也是啦)應(yīng)該最熟悉的是SimpleAdapter了吧,而且SimpleAdapter也可以實(shí)現(xiàn)在ListView顯示圖片,但是就是不能顯示網(wǎng)
絡(luò)圖片,只能顯示在drawalbe中定義過(guò)的圖片。所以就想,我是否可以改寫(xiě)SimpleAdapter的類,在它實(shí)例化drawalbe中圖片時(shí),我
替換成我自己 的顯示網(wǎng)絡(luò)圖片的方法呢?答案是肯定的?。ㄏ氆@取android的源碼,可以查看我的另一篇文章http://hulefei29./blog/615016)
第二步:源碼分析
經(jīng)過(guò)查看源碼SimpleAdapter發(fā)現(xiàn),顯示每個(gè)item視圖都是通過(guò)調(diào)用(int position, View convertView, ViewGroup parent)方法來(lái)實(shí)現(xiàn)的
-
- public View getView(int position, View convertView, ViewGroup parent) {
- return createViewFromResource(position, convertView, parent, mResource);
- }
/**
* @see android.widget.Adapter#getView(int, View, ViewGroup)
*/
public View getView(int position, View convertView, ViewGroup parent) {
return createViewFromResource(position, convertView, parent, mResource);
}
在getView(int position, View convertView, ViewGroup
parent)中又調(diào)用了SimpleAdapter的私有方法createViewFromResource來(lái)組裝View,在
createViewFromResource中對(duì)SimpleAdapter的參數(shù)String[] from
和int[] to進(jìn)行了組裝,代碼如下:
- private View createViewFromResource(int position, View convertView,
- ViewGroup parent, int resource) {
- View v;
- if (convertView == null) {
- v = mInflater.inflate(resource, parent, false);
-
- final int[] to = mTo;
- final int count = to.length;
- final View[] holder = new View[count];
-
- for (int i = 0; i < count; i++) {
- holder[i] = v.findViewById(to[i]);
- }
-
- v.setTag(holder);
- } else {
- v = convertView;
- }
-
- bindView(position, v);
-
- return v;
- }
private View createViewFromResource(int position, View convertView,
ViewGroup parent, int resource) {
View v;
if (convertView == null) {
v = mInflater.inflate(resource, parent, false);
final int[] to = mTo;
final int count = to.length;
final View[] holder = new View[count];
for (int i = 0; i < count; i++) {
holder[i] = v.findViewById(to[i]);
}
v.setTag(holder);
} else {
v = convertView;
}
bindView(position, v);
return v;
}
在createViewFromResource方法中又有一個(gè)bindView(position, v)方法對(duì)item中的各個(gè)View進(jìn)行了組裝,bindView(position, v)代碼如下:
- private void bindView(int position, View view) {
- final Map dataSet = mData.get(position);
- if (dataSet == null) {
- return;
- }
-
- final ViewBinder binder = mViewBinder;
- final View[] holder = (View[]) view.getTag();
- final String[] from = mFrom;
- final int[] to = mTo;
- final int count = to.length;
-
- for (int i = 0; i < count; i++) {
- final View v = holder[i];
- if (v != null) {
- final Object data = dataSet.get(from[i]);
- String text = data == null ? "" : data.toString();
- if (text == null) {
- text = "";
- }
-
- boolean bound = false;
- if (binder != null) {
- bound = binder.setViewValue(v, data, text);
- }
-
- if (!bound) {
- if (v instanceof Checkable) {
- if (data instanceof Boolean) {
- ((Checkable) v).setChecked((Boolean) data);
- } else {
- throw new IllegalStateException(v.getClass().getName() +
- " should be bound to a Boolean, not a " + data.getClass());
- }
- } else if (v instanceof TextView) {
-
-
- setViewText((TextView) v, text);
- } else if (v instanceof ImageView) {
- if (data instanceof Integer) {
- setViewImage((ImageView) v, (Integer) data);
- } else {
- setViewImage((ImageView) v, text);
- }
- } else {
- throw new IllegalStateException(v.getClass().getName() + " is not a " +
- " view that can be bounds by this SimpleAdapter");
- }
- }
- }
- }
- }
private void bindView(int position, View view) {
final Map dataSet = mData.get(position);
if (dataSet == null) {
return;
}
final ViewBinder binder = mViewBinder;
final View[] holder = (View[]) view.getTag();
final String[] from = mFrom;
final int[] to = mTo;
final int count = to.length;
for (int i = 0; i < count; i++) {
final View v = holder[i];
if (v != null) {
final Object data = dataSet.get(from[i]);
String text = data == null ? "" : data.toString();
if (text == null) {
text = "";
}
boolean bound = false;
if (binder != null) {
bound = binder.setViewValue(v, data, text);
}
if (!bound) {
if (v instanceof Checkable) {
if (data instanceof Boolean) {
((Checkable) v).setChecked((Boolean) data);
} else {
throw new IllegalStateException(v.getClass().getName() +
" should be bound to a Boolean, not a " + data.getClass());
}
} else if (v instanceof TextView) {
// Note: keep the instanceof TextView check at the bottom of these
// ifs since a lot of views are TextViews (e.g. CheckBoxes).
setViewText((TextView) v, text);
} else if (v instanceof ImageView) {
if (data instanceof Integer) {
setViewImage((ImageView) v, (Integer) data);
} else {
setViewImage((ImageView) v, text);
}
} else {
throw new IllegalStateException(v.getClass().getName() + " is not a " +
" view that can be bounds by this SimpleAdapter");
}
}
}
}
}
終于找到了對(duì)ViewImage進(jìn)行組裝的代碼了“else if (v instanceof ImageView)”,我們留成功之差一步之遙了!
看到上面茫茫的代碼是不是已經(jīng)頭暈了呢,其實(shí)以上的都是源代碼,我沒(méi)有做過(guò)任何的修改,也不需要修改,只是需要把它從SimpleAdapter中
取出來(lái)進(jìn)行覆蓋,以為他們私有方法,不能用super調(diào)用!到最后終于到你出手的時(shí)候了,你需要重寫(xiě)SimpleAdapter類中的
setViewText方法,SimpleAdapter對(duì)setViewText進(jìn)行了重載,有兩個(gè)方法,代碼如下:
- public void setViewImage(ImageView v, int value) {
- v.setImageResource(value);
- }
-
-
- public void setViewImage(ImageView v, String value) {
- try {
- v.setImageResource(Integer.parseInt(value));
- } catch (NumberFormatException nfe) {
- v.setImageURI(Uri.parse(value));
- }
- }
public void setViewImage(ImageView v, int value) {
v.setImageResource(value);
}
public void setViewImage(ImageView v, String value) {
try {
v.setImageResource(Integer.parseInt(value));
} catch (NumberFormatException nfe) {
v.setImageURI(Uri.parse(value));
}
}
setViewImage(ImageView v, int value)
你應(yīng)該一看就熟悉了吧,int就是R中的索引值,但是你還看到SimpleAdapter居然還有一個(gè)setViewImage(ImageView
v, String value)可以接受String的方法,在往下看就是知道了,如果不是索引,ImageView
也可以接受Uri的值來(lái)設(shè)置圖片,切忌Uri不是Url,所以我們只需要改寫(xiě)一下這個(gè)方法就ok了,代碼如下:
- public void setViewImage(ImageView v, String value) {
- Bitmap bitmap = WebImageBuilder.returnBitMap(value);
- ((ImageView) v).setImageBitmap(bitmap);
- }
public void setViewImage(ImageView v, String value) {
Bitmap bitmap = WebImageBuilder.returnBitMap(value);
((ImageView) v).setImageBitmap(bitmap);
}
我們用Bitmap
來(lái)對(duì)ImageView進(jìn)行設(shè)置,WebImageBuilder.returnBitMap是我自己實(shí)現(xiàn)的獲取網(wǎng)絡(luò)圖片的方法,當(dāng)然google下都是
的,在我下面的源碼中也有,在這里就不多說(shuō)了!說(shuō)到這,我的解釋也就說(shuō)完了,希望可以給你幫助!如果你是不愿意跟著別人思路走的人,希望自己研究出來(lái)的
話,那最后我也拿我的源碼貼上,對(duì)有些朋友來(lái)說(shuō)獲取直接看源碼,理解的更快吧!
最后強(qiáng)調(diào)一下,本文為胡樂(lè)費(fèi)的原創(chuàng),如果要轉(zhuǎn)載的話,希望注明出處!
本文轉(zhuǎn)自: http://hulefei29./blog/616262
|