2012-07-20 55 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

我認爲你應該讓該方法「同步」,即下載圖像。許多線程正在同時運行,所以有可能圖像出現在錯誤的地方。

相關問題