在自定义适配器的列表视图项中加载不同的图像

Posted

技术标签:

【中文标题】在自定义适配器的列表视图项中加载不同的图像【英文标题】:Loading different images in the listview item for custom Adapter 【发布时间】:2014-02-14 05:07:30 【问题描述】:

嗨,如果我在解释问题时弄错了,请原谅我。我有一个自定义基础适配器,其中有两个 imageView 和两个 TextView,我正在使用 Async 任务从 URL 设置图像。它会设置图像,但会再次自动更改图像。

下面是适配器的代码。

public class SharedPhotosAdapter extends BaseAdapter

Context context;
LayoutInflater inflater;
public static ArrayList<HashMap<String, String>> data;
ImageLoader imageLoader;
private static final String BRANCH="Branch";
private static final String DATE="DateTime";
private static final String STARS="Stars";
private static final String IMAGE_URL="URL";
private static final String USER_NAME="UserName";
 TextView name,date,comment;
 ImageView pro_image,shared_image;

 public SharedPhotosAdapter(Context con,ArrayList<HashMap<String, String>> result) 
    // TODO Auto-generated constructor stub

     context=con;
     data=result;
     inflater = (LayoutInflater)context.getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
     imageLoader=new ImageLoader(context);





@Override
public int getCount() 
    // TODO Auto-generated method stub
    return data.size();


@Override
public Object getItem(int arg0) 
    // TODO Auto-generated method stub
    return null;


@Override
public long getItemId(int arg0) 
    // TODO Auto-generated method stub
    return 0;


@Override
public View getView(int position, View rowView, ViewGroup parent) 
    // TODO Auto-generated method stub

     ViewHolder holder;
     Bitmap bitmap=null;
     ImageView image = null;
     HashMap<String, String> result=data.get(position);
    if(rowView==null)
    
        rowView=inflater.inflate(R.layout.shared_photos_item, null);
        holder=new ViewHolder();


    holder.name=(TextView)rowView.findViewById(R.id.textView1);
    holder.date=(TextView)rowView.findViewById(R.id.textView4);
    holder.comment=(TextView)rowView.findViewById(R.id.textView3);

    holder.pro_image=(ImageView)rowView.findViewById(R.id.imageView1);
    holder.shared_image=(ImageView)rowView.findViewById(R.id.imageView2);






    rowView.setTag(holder);


    
    else
    
        holder = (ViewHolder)rowView.getTag();

    

    new DownloadImageTask(holder.shared_image).execute(result.get(IMAGE_URL));
    holder.name.setText(result.get(USER_NAME));
    holder.date.setText(result.get(DATE));
    holder.comment.setText(result.get(BRANCH));





    return rowView;




public class ViewHolder

     TextView name,date,comment;
     ImageView pro_image,shared_image;






这是我用于从 url 设置图像的异步任务

public class DownloadImageTask extends AsyncTask<String, Void, Bitmap> 
ImageView bmImage;

public DownloadImageTask(ImageView bmImage) 
    this.bmImage = bmImage;


@Override
protected void onPreExecute() 
    // TODO Auto-generated method stub
    super.onPreExecute();



protected Bitmap doInBackground(String... urls) 
    String urldisplay = urls[0];
    Bitmap mIcon11 = null;
    try 
      InputStream in = new java.net.URL(urldisplay).openStream();
      mIcon11 = BitmapFactory.decodeStream(in);
     catch (Exception e) 

    
    return mIcon11;


@Override 
protected void onPostExecute(Bitmap result) 
    super.onPostExecute(result);

    bmImage.setImageBitmap(result);
 

它随机设置任何图像到图像视图只是无法弄清楚我哪里出错了。 会有一点帮助。

谢谢

【问题讨论】:

长话短说:为 android 使用一些图像加载器库 ... 长话短说:ListView 正在重用项目,在 getView 中您正在启动 AsyncTask,您滚动列表视图,现在行视图初始关联到 fx。: id=3 的项目现在与 id=15 的项目相关联,AsyncTask 完成并将图像从 id=3 的项目放入图像视图... 同意。您的方法有缺陷,因为ListViews 等将重新使用ImageViews,并且您必须取消为先前在同一ImageView 中使用的图像启动的任务。您还应该有一些缓存,这样您就不会一遍又一遍地下载图像。您必须正确处理许多微小的细节才能使其正常工作,而 UniversalImageLoader 或 Volley 等库可以为您做到这一点。 您不会保留在任何地方获取的图像,因此当您滚动时,您将一遍又一遍地获取相同的图像。如果视图有一个有效的“持有人”,它可能会包含之前获取的与不再可见的行相关联的图像。在启动异步任务之前,您至少应该在 getView 方法中设置 holder.sharedImage=null。但真正的解决方法是使用图像加载器,它会跟踪已下载的图像,然后您可以简单地将 holder.sharedImage 分配给该图像。 【参考方案1】:

我建议您尝试Picasso 以消除下载图像/缓存等的麻烦。 一旦你的工作空间中有了 jar,你需要在适配器类的 getView() 方法中做的就是这个。

Picasso.with(context).load(result.get(IMAGE_URL)).into(holder.shared_image);

不需要 DownloadAsyncTask。 正如@zapl 在评论中所建议的那样,还有其他库,如 Volley 和 UniversalImageLoader,但我喜欢 Picasso。您还可以使用 Picasso 提供的 Transformation 接口轻松应用圆形图像等转换。

【讨论】:

@droidx 我可以使用 getActivity()).load(imageURL) 代替 (context).load(result.get(IMAGE_URL)) 吗?这样可以吗?

以上是关于在自定义适配器的列表视图项中加载不同的图像的主要内容,如果未能解决你的问题,请参考以下文章

如何在自定义适配器上实现 onClickListener?

在 Picasso 图像加载器中加载位图图像会减慢列表视图中的滚动速度

Android:需要在自定义适配器列表视图中保存复选框状态

如何实现 Asynctask 在 ArrayAdapter 中加载图像

如何在列表视图中使用毕加索

listview 项目未在自定义适配器的 getview 方法中显示分配的值