2012-07-20 65 views
1

我有在ListView中使用AsyncTask加载图像的奇怪问题。在我的ListView中,每行都包含一个ImageView和一个TextView。我跟着这个链接吧:点击列表项时,图像在列表视图中交换它们的行

http://android-developers.blogspot.in/2010/07/multithreading-for-performance.html

的图像正在从URL成功下载并填写他们的尊重行。但是当我滚动ListView或点击任何列表项时,图像只是交换它们的行。尽管TextView中的文本保留在相同的行上。我不明白为什么会发生。我已经搜索了很多,但找不到它的完美理由。请帮忙。

这里是我的适配器类:

 private class ListAdapter extends BaseAdapter{ 

    private ArrayList<HashMap<String, Object>> allFriends; 
    private LayoutInflater mInflater; 

    public ListAdapter(ArrayList<HashMap<String, Object>> allFriends, Context context){ 
     this.allFriends = allFriends; 
     mInflater = LayoutInflater.from(context); 
    } 

    @Override 
    public int getCount() { 
     return allFriends.size(); 
    } 

    @Override 
    public Object getItem(int position) { 
     return allFriends.get(position); 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 

    @Override 
    public View getView(final int position, View convertView, ViewGroup parent) { 
     FriendsViewHolder holder; 

     if (convertView == null||!(convertView instanceof TextView)||!(convertView instanceof ImageView)) { 
      convertView = mInflater.inflate(R.layout.friend_list_view, null); 

      holder = new FriendsViewHolder(); 
      holder.friendName = (TextView) convertView.findViewById(R.id.friendName); 
      holder.friendImage = (ImageView) convertView.findViewById(R.id.friendImage);     

      convertView.setTag(holder); 
     }else { 
      holder = (FriendsViewHolder) convertView.getTag(); 
     } 

     holder.friendName.setText((String) allFriends.get(position).get(FriendsActivity.FRIENDS_NAME_KEY)); 

     String otherId=(String) allFriends.get(position).get(FriendsActivity.IDKEY); 
     String isImage=(String) allFriends.get(position).get(FriendsActivity.IS_IMAGE_KEY); 

      if(isImage.equalsIgnoreCase("true")){ 
       download(otherId, holder.friendImage); 
      } 

     return convertView; 
    } 
}//End of list adapter 

以及下载方法是:

public void download(String otherId, ImageView imageView) { 
    BitmapDownloaderTask task = new BitmapDownloaderTask(imageView); 
    task.execute(otherId); 
} 

这里BitmapDownloaderTask是异步任务下载图片:

class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> { 
     private String otherId; 
     private final WeakReference<ImageView> imageViewReference; 

     public BitmapDownloaderTask(ImageView imageView) { 
      imageViewReference = new WeakReference<ImageView>(imageView); 
     } 

     @Override 
     // Actual download method, run in the task thread 
     protected Bitmap doInBackground(String... params) { 
      // params comes from the execute() call: params[0] is the url. 

      return getOtherUserImage(params[0]); 
     } 

     @Override 
     // Once the image is downloaded, associates it to the imageView 
     protected void onPostExecute(Bitmap bitmap) { 
      if (isCancelled()) { 
       bitmap = null; 
      } 

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

而且getOtherUserImage方法是:

public Bitmap getOtherUserImage(String otherUserId){ 

    // code to download the image goes here. It returns bitmap "bmImg". 

    if(bmImg==null){ 
     return null; 
    }else { 
     bmImg = Bitmap.createScaledBitmap(bmImg,imageWidth, imageHeight, true); 

     /*availableFriends.get(position).put(BITMAP_KEY, bmImg); 
     runOnUiThread(new Runnable() { 
      public void run() { 
       adapter.notifyDataSetChanged(); 
      } 
     });*/ 
     return bmImg; 
    } 
} 
+0

你是否遵循查看持有者的方法?发布您的自定义适配器,看看发生了什么。 – 2012-07-20 12:53:04

+0

是的,我遵循ViewHolder方法。请参阅编辑。 – 2012-07-20 13:04:50

回答

1

这个Android Developer's Blog post描述了如何正确加载图像到一个ListView异步,并提供一个很好的示例应用程序,你应该能够快速和容易地修改(我做),以适应您的需求。

的确,对于存储器效率的原因,ListView回收的观点 时显示的用户滚动时。如果一个人在列表中跳过,则给定ImageView对象的 将被多次使用。每次显示 时,ImageView都会正确触发图像下载任务, 将最终更改其图像。那么问题在哪里?由于 与大多数并行应用程序,关键问题在于排序。在 我们的情况下,不能保证下载任务将以 的开始顺序完成。结果是最终显示在列表中的图像 可能来自之前的项目,其中 仅仅需要花费更长的时间才能下载。这不是一个问题 如果您下载的图像被一次性绑定并全部绑定到 ImageViews

+0

我已经尝试了上述链接中的方法,但它仍然无法正常工作。 :(更多的想法...... – 2012-09-04 05:27:16

+0

嗨,Jeff,我已经下载了上面链接给出的代码,并且我的代码也完全实现了它,并且我也能够缓存图像,但图像问题出现在错误的行中仍然存在,现在它不会在滚动上发生,因为我正在使用缓存,但有时在第一次打开屏幕时,它们已经出现在错误的地方了,在我的情况下,我没有使用“url”,因为我只有一个URL,我必须发送userId并获取他的图像。所以我使用Id而不是URL来区分图像的位置,但没有成功。有任何想法吗? – 2012-09-12 07:20:45

+0

好的,所以我终于做到了。但我在这里有一些小问题。我想在图像加载时显示默认图像。就像在这个链接:http://stackoverflow.com/questions/12386411/how-to-show-default-image-while-image-is-being-downloaded-using-asynctask – 2012-09-12 11:12:12

0

我认为你应该让该方法“同步”,即下载图像。许多线程正在同时运行,所以有可能图像出现在错误的地方。

相关问题