在列表视图中从URL加载图像

时间:2015-01-21 07:54:42

标签: java android listview

我可以下载图像并在ListView中显示它。但我面临的问题是, 当我加载图像时,它们都被加载到列表的第一行。它显示在第一行中逐个加载。而其他行保留默认图像。它看起来很奇怪。该怎么办。以下代码:

            private class simpsync extends AsyncTask<String, Integer , Bitmap>{
                private final WeakReference imageViewReference;
                simpsync(ImageView iv){
                    //imageView=iv;
                    imageViewReference=new WeakReference(iv);

                }
                @Override
                protected Bitmap doInBackground(String... param) {

                    Bitmap bmp=CommonFunctions.overlay(CommonFunctions.loadUrlBitmap(param[0]));
                    return bmp;
                }
                  protected void onPostExecute(Bitmap bitmap) {

                      //imageView.setImageBitmap(result);
                      if (isCancelled()) {
                            bitmap = null;
                        }
                        if (imageViewReference != null) {
                            ImageView imageView = (ImageView) imageViewReference.get();
                            if (imageView != null) {

                                if (bitmap != null) {
                                    imageView.setImageBitmap(bitmap);
                                }
                                }
                            }
                  }
            }

此代码是BaseAdapter类的getView函数

            public View getView(int position, View convertView, ViewGroup parent) {

                View vi = convertView;
                ViewHolder holder;

                if(convertView==null){

                    /****** Inflate tabitem.xml file for each row ( Defined below ) *******/
                    //list_book_detail_entry
                    if(requestType==SearchAndIndex.SEARCH_IN_SEPAERATE)
                    {
                        vi = inflater.inflate(R.layout.list_book_detail_buy, parent, false);
                        //vi = inflater.inflate(R.layout.list_book_detail_buy, null);
                    }
                    else{
                        vi = inflater.inflate(R.layout.list_book_detail_entry, parent, false);
                        //vi = inflater.inflate(R.layout.list_book_detail_entry, parent, false);
                    }


                    /****** View Holder Object to contain tabitem.xml file elements ******/

                    holder = new ViewHolder();

                    holder.bookTitle=(TextView)vi.findViewById(R.id.BookTitle);
                    holder.writer = (TextView) vi.findViewById(R.id.WriterName);
                    holder.imageUrl=(ImageView)vi.findViewById(R.id.ImageUrl);
                    holder.isbn=(TextView)vi.findViewById(R.id.BookISBN);
                    holder.serialNumber=(TextView)vi.findViewById(R.id.BookSerialNumber);
                    holder.availabilityView=(ImageView)vi.findViewById(R.id.AvailabilityView);
                    holder.publisher=(TextView)vi.findViewById(R.id.Publisher);
                    holder.publishingDate=(TextView)vi.findViewById(R.id.PublishingDate);
                    /************  Set holder with LayoutInflater ************/
                    vi.setTag( holder );
                }
                else 
                    holder=(ViewHolder)vi.getTag();

                if(data.size()<=0)
                {
                    holder.bookTitle.setText("--");
                    holder.writer.setText("--");
                    holder.publisher.setText("--");
                    holder.publisher.setText("----+--+--");
                }
                else
                {
                    tempValues=null;
                    tempValues = ( BookDetailsStruct ) data.get( position );
                    holder.writer.setText( tempValues.Writer );
                    holder.publisher.setText(tempValues.Publisher);
                    holder.publishingDate.setText(tempValues.getIssueDetail(0).publishingDate);

                    simpsync sp=new simpsync(holder.imageUrl);
                    if(requestType==SearchAndIndex.SEARCH_IN_SEPAERATE)
                     {
                         if(tempValues.getIssueDetail(0)!=null)
                         {
                             String toAdd;
                             if(tempValues.getIssueDetail(0).serialNumber==-1)
                                 toAdd="";
                             else
                                 toAdd=" [ 巻"+tempValues.getIssueDetail(0).serialNumber+" ]";
                             holder.bookTitle.setText( tempValues.BookName+toAdd);
                             sp.execute(tempValues.getIssueDetail(0).smallImageUrl);
                         }
                     }
                     else{
                         if(tempValues.largetNumberIndex!=-1)
                         {
                             String toAdd;
                             if(tempValues.getIssueDetail(tempValues.largetNumberIndex).serialNumber==-1)
                                 toAdd="";
                             else
                                 toAdd=" ("+tempValues.getIssueCount()+"巻)";
                             holder.bookTitle.setText( tempValues.BookName+toAdd);
                             sp.execute(tempValues.getIssueDetail(tempValues.largetNumberIndex).smallImageUrl);
                         }
                         else{
                             holder.bookTitle.setText( tempValues.BookName);
                             sp.execute(tempValues.getIssueDetail(0).smallImageUrl);
                         }
                     }
                     vi.setOnClickListener(new OnItemClickListener( position ));
                }
                return vi;

            }

如果您有任何其他问题,请告诉我

2 个答案:

答案 0 :(得分:2)

“问题”是ListView的回收行为。你不够尊重它。当您向下滚动并且视图在顶部消失时,它将在底部重复使用(这就是为什么您使用ViewHolder模式,这很好)。但是你也启动了一个异步任务并给它ImageView并保持它。由于行的整个视图(以及图像视图)被回收,因此它不符合垃圾收集的条件,因此asynctask有一个有效的ImageView,一旦完成就会显示图像。

为了纠正你的代码,我建议你简单地调整android开发者页面上的内容,它几乎是你可以使用的复制过去准备代码: Load Bitmaps into a GridView Implementation

你也可以使用第三方库,因为其他聪明人也遇到了这个问题,并提出了很好的解决方案:

  1. Glide
  2. Picasso
  3. 他们都有非常(非常)简单的Api来完成工作,并且它们都是高效且可调的,默认设置已经很好。

答案 1 :(得分:1)

您可以使用Picasso将图片加载到ListView

@Override 
public void getView(int position, View convertView, ViewGroup parent) {
  SquaredImageView view = (SquaredImageView) convertView;
  if (view == null) {
    view = new SquaredImageView(context);
  }
  String url = getItem(position);

  Picasso.with(context).load(url).into(view);
}

OR

@Override 
public void getView(int position, View convertView, ViewGroup parent) {
  View v = convertView;

  ImageView imgView = v.findViewById(R.id.someImageView);

  String url = getItem(position);

  Picasso.with(context).load(url ).into(imgView);
}

Picasso自动处理Android上图像加载的许多常见缺陷:

  1. ImageView
  2. 中处理adapter回收和下载取消
  3. 使用最少内存的复杂图像转换。
  4. 自动内存和磁盘缓存。