2014-01-07 58 views
0

我有很長的ListView,其中每行有ImageView。它顯示正確的位圖,如果我慢慢滾動列表(每行有不同的圖標顯示)。快速滾動時圖像未加載到ListView中

當我快速滾動ListView時出現問題。發生這種情況的原因是很多圖像並未加載到它們的ImageView中,使其透明。即使是之前顯示的緩慢滾動列表。

這裏是getView()方法中的代碼應該顯示的圖標:

 BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inPreferredConfig = Bitmap.Config.ARGB_8888; 
     String name = ... //custom code to get the icon name to show 
     Bitmap bitmap = BitmapFactory.decodeFile(getIconsDir() + name + getIconsExt(), options); 
     holder.imgIcon.setImageBitmap(bitmap); 

我回收convertView在適配器的getView()方法。

我知道該位置存在的位圖。 imgIcon是該行的ViewHolder所引用的ImageView

我也試過使用圖像加載器(如畢加索),但我得到了同樣的結果。

以前有沒有人經歷過這個?

回答

2

不要在適配器的getView()中進行位圖解碼。它會導致ListView滯後並且也會非常快地填滿RAM。

您應該:

  1. 使用一個規模有限,內存緩存守住位圖。
  2. 異步解碼和加載視圖中的圖像。

ListView重新循環視圖,並且設備內存可能無法保存所有時間加載的所有位圖。即使圖像加載庫也面臨這個問題。

+0

好的,但畢加索應該使用內存緩存和異步加載,不是嗎? –

+0

@DanieleVitali是的,它可能會。但這並不意味着您的列表視圖將始終立即加載所有內容,並且在滾動速度非常快時看起來像素完美。 –

+0

所以我得出結論,即使有內存緩存和異步加載,我仍然可以在ListView中顯示圖像時出現問題嗎? –

0

是的,ListViews中的圖像存在性能問題。 但是,以任何方式預取圖像都是一種可以避免調用讀取文件系統操作和解碼二進制數據的方法。 我將您在viewviews中存儲的視圖標記保存在convertviews - 標記中。

0

從磁盤加載圖像是一種緩慢的操作,因此可以將它們從存儲在其中的任何壓縮格式(如JPG或PNG)解碼爲位圖。所以理想情況下,它不應該在主線程的getView()中完成。而且,它們佔用了大量的內存。

如果這些「圖標」是靜態的,您應該將它們包含爲可繪製資源,然後使用ImageView.setImageResource。然後操作系統會找出如何最優化地加載它們(加上,這樣你就可以獲得給定屏幕的正確分辨率)。

如果圖標不是靜態的(例如從網絡加載),我推薦使用帶有異步加載器的內存緩存,但要確保它的大小有限和/或使用弱引用(但要小心:Android一般建議不要使用弱/軟引用,尤其是對於位圖,因爲分配給位圖的內存是本地代碼,所以垃圾收集器不知道這些圖像真正佔用了多少內存,並且它可能決定不收集它們,即使它的內存不足......因爲它認爲它們很小)。

+0

好的,但畢加索應該使用內存緩存和異步加載,不是嗎? –

+0

我對Picasso並不熟悉,但我猜如果它確實使用異步加載和內存緩存,那麼確定,在滾動速度很快時可能不會立即加載圖像。他們應該在幾毫秒後加載罰款 - 如果你減慢某些項目的滾動。 –