2012-05-02 132 views
1

我已經使用Listview/customcursoradapter創建了一個配方列表。自定義佈局包含配方的照片,現在我在查看和滾動ListView的性能方面遇到了一些問題,儘管它只有10條記錄(目標是150)。有時我得到這個錯誤java.lang.OutOfMemoryError: bitmap size exceeds VM budget,我試圖實施AsyncTask,但我沒有做到這一點。有什麼辦法可以解決這個問題嗎?ListView性能下降

您的幫助是高度讚賞!

這裏是我的getView方法

public View getView(int position, View convertView, ViewGroup parent) { 
    View row = super.getView(position, convertView, parent); 
    Cursor cursbbn = getCursor(); 
    if (row == null) 
    { 
     LayoutInflater inflater = (LayoutInflater) localContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     row = inflater.inflate(R.layout.listtype, null); 
    } 

    String Title = cursbbn.getString(2); 
    String SandID=cursbbn.getString(1); 
    String Readyin = cursbbn.getString(4); 
    String Faovoites=cursbbn.getString(8); 

    TextView titler=(TextView)row.findViewById(R.id.listmaintitle); 
    TextView readyinr=(TextView)row.findViewById(R.id.listreadyin); 

    int colorPos = position % colors.length; 
    row.setBackgroundColor(colors[colorPos]); 

    titler.setText(Title); 
    readyinr.setText(Readyin); 

    ImageView picture = (ImageView) row.findViewById(R.id.imageView1); 

    Bitmap bitImg1 = BitmapFactory.decodeResource(localContext.getResources(), R.drawable.rec0001); 
    Bitmap bitImg2 = BitmapFactory.decodeResource(localContext.getResources(), R.drawable.rec0002); 
    Bitmap bitImg3 = BitmapFactory.decodeResource(localContext.getResources(), R.drawable.rec0003); 
    Bitmap bitImg4 = BitmapFactory.decodeResource(localContext.getResources(), R.drawable.rec0004); 
    Bitmap bitImg5 = BitmapFactory.decodeResource(localContext.getResources(), R.drawable.rec0005); 
    Bitmap bitImg6 = BitmapFactory.decodeResource(localContext.getResources(), R.drawable.rec0006); 
    Bitmap bitImg7 = BitmapFactory.decodeResource(localContext.getResources(), R.drawable.rec0007); 
    Bitmap bitImg8 = BitmapFactory.decodeResource(localContext.getResources(), R.drawable.rec0008); 
    Bitmap bitImg9 = BitmapFactory.decodeResource(localContext.getResources(), R.drawable.rec0009); 
    Bitmap bitImg10 = BitmapFactory.decodeResource(localContext.getResources(), R.drawable.rec0010); 

    if(SandID.contentEquals("0001")) 
     picture.setImageBitmap(getRoundedCornerImage(bitImg1)); 

    if(SandID.contentEquals("0002")) 
     picture.setImageBitmap(getRoundedCornerImage(bitImg2)); 

    if(SandID.contentEquals("0003")) 
     picture.setImageBitmap(getRoundedCornerImage(bitImg3)); 

    if(SandID.contentEquals("0004")) 
     picture.setImageBitmap(getRoundedCornerImage(bitImg4)); 

    if(SandID.contentEquals("0005")) 
     picture.setImageBitmap(getRoundedCornerImage(bitImg5)); 

    if(SandID.contentEquals("0006")) 
     picture.setImageBitmap(getRoundedCornerImage(bitImg6)); 
    if(SandID.contentEquals("0007")) 
     picture.setImageBitmap(getRoundedCornerImage(bitImg7)); 
    if(SandID.contentEquals("0008")) 
     picture.setImageBitmap(getRoundedCornerImage(bitImg8)); 
    if(SandID.contentEquals("0009")) 
     picture.setImageBitmap(getRoundedCornerImage(bitImg9)); 

    if(SandID.contentEquals("0010")) 
     picture.setImageBitmap(getRoundedCornerImage(bitImg10)); 

    return row; 
} 

,這是錯誤:

05-02 03:11:55.898: E/AndroidRuntime(376): FATAL EXCEPTION: main 
05-02 03:11:55.898: E/AndroidRuntime(376): java.lang.OutOfMemoryError: bitmap size exceeds VM budget 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:460) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:359) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:385) 
05-02 03:11:55.898: E/AndroidRuntime(376): at master.chef.mediamaster.AlternateRowCursorAdapter.getView(AlternateRowCursorAdapter.java:83) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.widget.AbsListView.obtainView(AbsListView.java:1409) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.widget.ListView.makeAndAddView(ListView.java:1745) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.widget.ListView.fillUp(ListView.java:700) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.widget.ListView.fillGap(ListView.java:646) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.widget.AbsListView.trackMotionScroll(AbsListView.java:3399) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.widget.AbsListView.onTouchEvent(AbsListView.java:2233) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.widget.ListView.onTouchEvent(ListView.java:3446) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.view.View.dispatchTouchEvent(View.java:3885) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:903) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942) 
05-02 03:11:55.898: E/AndroidRuntime(376): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1691) 
05-02 03:11:55.898: E/AndroidRuntime(376): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1125) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.app.Activity.dispatchTouchEvent(Activity.java:2096) 
05-02 03:11:55.898: E/AndroidRuntime(376): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1675) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2194) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.view.ViewRoot.handleMessage(ViewRoot.java:1878) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.os.Handler.dispatchMessage(Handler.java:99) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.os.Looper.loop(Looper.java:123) 
05-02 03:11:55.898: E/AndroidRuntime(376): at android.app.ActivityThread.main(ActivityThread.java:3683) 
05-02 03:11:55.898: E/AndroidRuntime(376): at java.lang.reflect.Method.invokeNative(Native Method) 
05-02 03:11:55.898: E/AndroidRuntime(376): at java.lang.reflect.Method.invoke(Method.java:507) 
05-02 03:11:55.898: E/AndroidRuntime(376): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 
05-02 03:11:55.898: E/AndroidRuntime(376): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 
05-02 03:11:55.898: E/AndroidRuntime(376): at dalvik.system.NativeStart.main(Native Method) 

回答

3

首先,你是不是利用convertView的,你應該開始喜歡,

View view = convertView; 
if (view == null) { 
    // inflate 
} 

這是一篇博客文章,談論如何使用convertView,

http://android-er.blogspot.com/2010/06/using-convertview-in-getview-to-make.html

其次,你應該只針對解碼,你知道你將使用位圖。所以改變你的方法,

if(SandID.contentEquals("0001")) 
    Bitmap bitImg1 = BitmapFactory.decodeResource(localContext.getResources(), R.drawable.rec0001); 
    picture.setImageBitmap(getRoundedCornerImage(bitImg1)); 
... 

第三,你可以解碼他們一次,並讓他們在這種方法之外?例如,在構造函數中將它們解碼一次,然後將它們作爲實例成員存儲在適配器類中,然後在getView()中使用它們。

四,你回收你的位圖嗎?位圖的分配方式與其他對象的分配方式不同,並且在完成使用時需要調用它們的方法recycle()。如果你可以實現上面的第三項,你可以在大多數情況下避免這種複雜性,儘管你應該在你的活動停止時釋放它們,當它開始時重新分配它們。

有對SO有關Bitmap.recycle()很多很好的信息,我建議你花一些時間來研究它。解釋錯綜複雜超出了這裏可以完成的任務。這裏有一個很好的SO覆蓋後的話題,

Bitmap, Bitmap.recycle(), WeakReferences, and Garbage Collection

+0

我試圖實現轉換的看法,但我得到的10條記錄具有相同名稱??? –

+0

它不是這種情況,當我使用視圖行= super.getView(位置,convertView,父母); –

+0

轉換視圖是一個「回收」視圖。您仍然需要將所有值設置爲各種文本/圖像/等視圖。唯一不同的是你可以避免誇大一個新的觀點,這是相當昂貴的。 –