2012-06-25 42 views
19

我的ListView中的每個項目都包含一個ImageView和一個TextView,這將填充遠程信息。另一個getView被多次調用

我得到了一個URL爲ImageView,因此我開始AsyncTask下載圖像,並將下載的位圖調用setImageBitmap

這很好,但是當創建ListView時,經常會調用getView()。 它調用前10行getView的7倍(只有7個可見)。 (所以:0,1等,10,0,1等)。

然後我可以順利地滾動到第10項。但是之後,對於每個新行,listview再次調用前10個項目的getView的7倍。 (這會造成滯後..)

但是當我從AsyncTask刪除setImageBitmap,這一切都不會發生!

可能是什麼問題?難道這是一些佈局是大的,這將導致另一條getViews?

這裏一些代碼:

<ListView 
    android:id="@+id/mylist" 
    android:layout_width="wrap_content" 
    android:layout_height="fill_parent" 
    android:layout_alignParentBottom="true" 
    android:layout_below="@+id/mydivider" 
    android:divider="@+color/mycolor" 
    android:dividerHeight="2dp" 
    android:fadingEdge="none" 
    android:fastScrollEnabled="true" 
    android:listSelector="@android:color/transparent" 
    android:scrollbars="horizontal" 
    android:scrollingCache="false" 
    android:smoothScrollbar="false" /> 

的的AsyncTask:

public static class MyTask extends AsyncTask<String, Integer, Bitmap> { 
    private LruCache<String, Bitmap> mMap; 
    private String mUri; 
    private int mPosition; 
    private ViewHolder mHolder; 

    public MyTask (ViewHolder holder, int position, LruCache<String, Bitmap> map) { 
     mMap = map; 
     mHolder = holder; 
     mPosition = position; 
    } 

    @Override 
    protected Bitmap doInBackground(String... url) { 
     mUri = url[0]; 
     return getBitmapFromURL(mUri); 
    } 

    @Override 
    protected void onPostExecute(Bitmap b) { 
     if (b != null) { 
      mMap.put(mUri, b); 
      if (mPosition == mHolder.position) { 
       holder.image.setImageBitmap(b); 
      } 
     } 
    }; 
} 

getView()

row = convertView; 
ViewHolder holder; 
if (row == null) { 
    row = vi.inflate(R.layout.mylayout, null); 
    holder = new ViewHolder(); 
    holder.image = (ImageView) row.findViewById(R.id.myimage); 
    holder.title = (TextView) row.findViewById(R.id.mytext); 
    row.setTag(holder); 
} else { 
    holder = (ViewHolder) row.getTag(); 
} 

holder.title.setText("text"); 
holder.image.setImageResource(R.drawable.mydefaulticon); 
holder.position = position; 
startMyTask(content, holder, position); 

一些更多的信息:

當新視圖創建堆棧跟蹤顯示n中的getView從ListView.makeAndAddView() 稱爲但是在getViews的無用連勝它是從ListView.measureHeigthOfChildren()

所以好像當我設置位圖的佈局發生變化來了...

+0

是看起來那麼即使我認爲家長應重新佈局時,圖像會添加它自身作爲父高度也得到由that..But影響,這是我想不知道.. –

回答

32

的問題是在ListView的佈局。

參數layout_width設置爲wrap_content當我把它改成fill_parent問題就消失了......

+2

感謝您的支持。工作100%。 – Ron

+0

也爲我工作。我想知道它是否與listView的內在大小有限,如果它匹配它的父代而不是填充它?更大的listView會更頻繁地在邏輯上調用getView(),因爲有更多的單個項目可用。 –

+1

在我的情況下,即使這個特定的位置沒有特別的東西,getView被重複和無限地調用一個位置。我有多個視圖類型,就像在同一個屏幕上以及另一個視圖類型一樣。問題是我在佈局中有多個項目,其中一個項目的寬度由layoutWeight =「1」確定,以便在其他小部件之後佔用剩餘空間。重新排列這個固定的寬度解決了這個問題。 – velis

2

問題是您的ListView不知道每個項目是什麼。初始化時,ListView將測量其所有子級並根據此信息進行抽取。你在做什麼AsyncTask,正在改變列表中項目的大小,而不是讓ListView完全繪製自己。這會導致您的ListView表現不佳。

解決方案:您應該通過在您的AsyncTask的PostExecute中使用notifyDataSetChanged()通知適配器來更新您的ListView。這將允許ListView使用新信息繪製自己。

我希望它的作品!

一些有益的鏈接:

http://thinkandroid.wordpress.com/2012/06/13/lazy-loading-images-from-urls-to-listviews/

Lazy load of images in ListView

+0

看看這個鏈接: http://stackoverflow.com/a/5092426/929075當我只想更新一個視圖時,notifyDataSetChanged不起作用。我不會更改ArrayList –

0

對不起,遲到的答覆。我在我的圖庫插件適配器中遇到了同樣的問題。我曾經使用過Universal Image Loader。 Martijn的解決方案爲我工作。我所要做的只是在圖像完全下載並設置了imageView時添加notifyDataSetChanged()

0

我嘗試使用fill_parent作爲ListView中的高度,但我無法實現它完美,但我怎麼試過它通過防止創建convertViews,如果它已經存在。它在我的appoach中工作正常。

 @Override 
     public View getView(final int position, View convertView, ViewGroup parent) { 
     if (convertView != null) 
      return convertView; 
     else { 
      //your code... 
     } 
    }