ljrao
ljrao
2011-04-21 16:55

下载问题

已采纳

我现在想要用android的listview来显示从服务器上下载的图片该怎么做?像图片中这样

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

1条回答

  • songhuidanoop songhuidanoop 10年前

    第一步:分析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)方法来实现的

    Java代码
    /**
    * @see android.widget.Adapter#getView(int, View, ViewGroup)
    /

    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)中又调用了SimpleAdapter的私有方法createViewFromResource来组装View,在createViewFromResource中对SimpleAdapter的参数String[] from

    和int[] to进行了组装,代码如下:

    Java代码
    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方法中又有一个bindView(position, v)方法对item中的各个View进行了组装,bindView(position, v)代码如下:

    Java代码
    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");    
                     }    
                 }    
             }    
         }    
     }   
    

    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进行了重载,有两个方法,代码如下:

    Java代码
    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) 你应该一看就熟悉了吧,int就是R中的索引值,但是你还看到SimpleAdapter居然还有一个setViewImage(ImageView v, String value)可以接受String的方法,在往下看就是知道了,如果不是索引,ImageView 也可以接受Uri的值来设置图片,切忌Uri不是Url,所以我们只需要改写一下这个方法就ok了,代码如下:
    

    Java代码
    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 来对ImageView进行设置,WebImageBuilder.returnBitMap是我自己实现的获取网络图片的方法,当然google下都是的,在我下面的源码中也有,在这里就不多说了!说到这,我的解释也就说完了,希望可以给你帮助!如果你是不愿意跟着别人思路走的人,希望自己研究出来的话,那最后我也拿我的源码贴上,对有些朋友来说获取直接看源码,理解的更快吧!

    最后强调一下,本文为胡乐费的原创,如果要转载的话,希望注明出处!

    点赞 评论 复制链接分享