android ListView显示网络图片
研究了android两个礼拜,稍微有了点眉目,开始正式帮公司开发应用的时候,发现ListView没有现成的显示网络图片的类或方法,网上查了查也没找到好的解决方法。心一横,自己研究吧,现在把我的解决办法和大家分享一下。
使用ListView的方法就不在此介绍了,google一下都是的。
第一步:分析api
使用ListView都需要使用Adapter,而api中的adapter都继承自BaseAdapter,所以第一反应就是自己实现一个继承自BaseAdapter的adapter,但是BaseAdapter还是属于高度抽象的基类,所以实现起来还是还是有点难度的。此时作为初学者的你(当然我也是啦)应该最熟悉的是SimpleAdapter了吧,而且SimpleAdapter也可以实现在ListView显示图片,但是就是不能显示网络图片,只能显示在drawalbe中定义过的图片。所以就想,我是否可以改写SimpleAdapter的类,在它实例化drawalbe中图片时,我替换成我自己 的显示网络图片的方法呢?答案是肯定的!(想获取android的源码,可以查看我的另一篇文章http://hulefei29.iteye.com/blog/615016)
第二步:源码分析
经过查看源码SimpleAdapter发现,显示每个item视图都是通过调用(int position, View convertView, ViewGroup parent)方法来实现的
/*** @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)中又调用了SimpleAdapter的私有方法createViewFromResource来组装View,在createViewFromResource中对SimpleAdapter的参数String[] from
和int[] to进行了组装,代码如下:
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方法中又有一个bindView(position, v)方法对item中的各个View进行了组装,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) {// 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");}}}}}
终于找到了对ViewImage进行组装的代码了“else if (v instanceof ImageView)”,我们留成功之差一步之遥了!
看到上面茫茫的代码是不是已经头晕了呢,其实以上的都是源代码,我没有做过任何的修改,也不需要修改,只是需要把它从SimpleAdapter中取出来进行覆盖,以为他们私有方法,不能用super调用!到最后终于到你出手的时候了,你需要重写SimpleAdapter类中的setViewText方法,SimpleAdapter对setViewText进行了重载,有两个方法,代码如下:
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) 你应该一看就熟悉了吧,int就是R中的索引值,但是你还看到SimpleAdapter居然还有一个setViewImage(ImageView v, String value)可以接受String的方法,在往下看就是知道了,如果不是索引,ImageView 也可以接受Uri的值来设置图片,切忌Uri不是Url,所以我们只需要改写一下这个方法就ok了,代码如下:
public void setViewImage(ImageView v, String value) {Bitmap bitmap = WebImageBuilder.returnBitMap(value);((ImageView) v).setImageBitmap(bitmap);}
我们用Bitmap 来对ImageView进行设置,WebImageBuilder.returnBitMap是我自己实现的获取网络图片的方法,当然google下都是的,在我下面的源码中也有,在这里就不多说了!说到这,我的解释也就说完了,希望可以给你帮助!如果你是不愿意跟着别人思路走的人,希望自己研究出来的话,那最后我也拿我的源码贴上,对有些朋友来说获取直接看源码,理解的更快吧!
最后强调一下,本文为胡乐费的原创,如果要转载的话,希望注明出处!
本文转自: http://hulefei29.iteye.com/blog/616262
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
