2015-10-07 143 views
0

我有一個包含很多行的ListView。每行包含文本和圖像。 我擴展了BaseAdapter來創建一個ListAdapter,它加載一個圖像Picasso在ListAdapter中使用ImageView時OutOfMemoryError?

她是我的ListAdapter:

public class ServiceCardDtoListAdapter extends BaseAdapter { 

... 

@Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
    return createViewFromResource(position, convertView, parent, mResource); 
    } 

    private View createViewFromResource(int position, View convertView, ViewGroup parent, 
             int resource) { 

    RoundedImageView imageView = null; 
    TextView title = null; 
    TextView location = null; 

    if (convertView == null) { 
     convertView = inflater.inflate(resource, parent, false); 
    } 

    try { 
     imageView = (RoundedImageView)convertView.findViewById(R.id.service_card_imageview); 
     title = (TextView)convertView.findViewById(R.id.service_card_title); 
     location = (TextView)convertView.findViewById(R.id.service_card_location); 
    } 
    catch (Exception e) { 
     Log.e("ServiceCardDtoListAdapter", "Cannot create view resource IDs are missing", e); 
    } 

    // get the correct service_card 
    ServiceCardDto item = items.get(position); 

    // fill the view 
    Picasso.with(context) 
     .load(item.getImageUrls().get(0)) 
     .placeholder(R.drawable.card_image) 
     .error(R.drawable.card_image) 
     .centerCrop() 
     .fit() 
     .into(imageView); 


    title.setText(item.getTitle()); 
    location.setText(item.getCompanyName()); 

    return convertView; 
    } 

} 

這裏是滿級:https://gist.github.com/confile/a6ed64bde15aca44fd06

當向下滾動列表我得到了很多的內存警告和一對夫婦的圖片我的名單崩潰之後。以下是錯誤我得到:

10-07 02:41:07.724 4482-4482/? I/art: Clamp target GC heap from 67MB to 64MB 
10-07 02:41:07.724 4482-4482/? I/art: Alloc concurrent mark sweep GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 1% free, 63MB/64MB, paused 546us total 11.300ms 
10-07 02:41:07.724 4482-4482/? E/art: Throwing OutOfMemoryError "Failed to allocate a 15321612 byte allocation with 678832 free bytes and 662KB until OOM" 
10-07 02:41:07.724 4482-4482/? D/skia: --- allocation failed for scaled bitmap 
10-07 02:41:07.724 4482-4482/? D/AndroidRuntime: Shutting down VM 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime: FATAL EXCEPTION: main 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime: Process: com.lorentzos.swipecards.example, PID: 4482 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime: java.lang.OutOfMemoryError: Failed to allocate a 15321612 byte allocation with 678832 free bytes and 662KB until OOM 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at dalvik.system.VMRuntime.newNonMovableArray(Native Method) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:609) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:988) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.content.res.Resources.loadDrawableForCookie(Resources.java:2474) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.content.res.Resources.loadDrawable(Resources.java:2381) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.content.res.Resources.getDrawable(Resources.java:787) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.content.res.Resources.getDrawable(Resources.java:752) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at com.squareup.picasso.RequestCreator.getPlaceholderDrawable(RequestCreator.java:676) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at com.squareup.picasso.RequestCreator.into(RequestCreator.java:637) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at com.squareup.picasso.RequestCreator.into(RequestCreator.java:601) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at com.lorentzos.swipecards.ServiceCardDtoListAdapter.createViewFromResource(ServiceCardDtoListAdapter.java:84) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at com.lorentzos.swipecards.ServiceCardDtoListAdapter.getView(ServiceCardDtoListAdapter.java:57) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at com.lorentzos.flingswipe.SwipeFlingAdapterView.layoutChildren(SwipeFlingAdapterView.java:158) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at com.lorentzos.flingswipe.SwipeFlingAdapterView.refresh(SwipeFlingAdapterView.java:149) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at com.lorentzos.swipecards.MyActivity$1.onTabSelected(MyActivity.java:78) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.support.design.widget.TabLayout.selectTab(TabLayout.java:837) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.support.design.widget.TabLayout.selectTab(TabLayout.java:809) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.support.design.widget.TabLayout$Tab.select(TabLayout.java:1077) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.support.design.widget.TabLayout$1.onClick(TabLayout.java:643) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.view.View.performClick(View.java:4780) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.view.View$PerformClick.run(View.java:19866) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.os.Handler.handleCallback(Handler.java:739) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.os.Handler.dispatchMessage(Handler.java:95) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.os.Looper.loop(Looper.java:135) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at android.app.ActivityThread.main(ActivityThread.java:5257) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at java.lang.reflect.Method.invoke(Native Method) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at java.lang.reflect.Method.invoke(Method.java:372) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) 
10-07 02:41:07.725 4482-4482/? E/AndroidRuntime:  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) 

我怎樣纔能有效地回收了的ImageView以防止內存泄漏?

+0

您應該有效地重新調整位圖http://developer.android.com/training/displaying-bitmaps/load-bitmap.html – Sheychan

回答

1

我相信你的問題在你的placeholderImage。你應該檢查R.drawable.card_image的大小。嘗試刪除佔位符並運行一些測試。

關於優化

好了,有效地回收,列表和新材料標準,你應該使用RecyclerView。 RecyclerView的核心是模塊化和優化。它非常流暢和可擴展。

但這並不意味着你不能優化你的列表視圖。您可以實施ViewHolder pattern。當然,你會獲得一些記憶。從Android ViewHolder Pattern Example

// ViewHolder. 
static class ViewHolderItem { 
    TextView textViewItem; 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 

    ViewHolderItem viewHolder; 


    // The convertView argument is essentially a "ScrapView" as described is Lucas post 
    // http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/ 
    // It will have a non-null value when ListView is asking you recycle the row layout. 
    // So, when convertView is not null, you should simply update its contents instead of inflating a new row layout. 

    if(convertView==null){ 

    // inflate the layout 
    LayoutInflater inflater = ((Activity) mContext).getLayoutInflater(); 
    convertView = inflater.inflate(layoutResourceId, parent, false); 

    // well set up the ViewHolder 
    viewHolder = new ViewHolderItem(); 
    viewHolder.textViewItem = (TextView) convertView.findViewById(R.id.textViewItem); 

    // store the holder with the view. 
    convertView.setTag(viewHolder); 

    }else{ 
    // we've just avoided calling findViewById() on resource everytime 
    // just use the viewHolder 
    viewHolder = (ViewHolderItem) convertView.getTag(); 
    } 

    // object item based on the position 
    ObjectItem objectItem = data[position]; 

    // assign values if the object is not null 
    if(objectItem != null) { 
    // get the TextView from the ViewHolder and then set the text (item name) and tag (item ID) values 
    viewHolder.textViewItem.setText(objectItem.itemName); 
    viewHolder.textViewItem.setTag(objectItem.itemId); 
    } 
    return convertView; 
} 

採取 代碼你也應該記住,在一般的Android應用程序沒有什麼太大的可用資源。也就是說,你應該始終考慮圖像的最終尺寸。總是避免加載大於你需要的圖像。 如果您的應用程序會消耗更多的內存,那麼通常的應用程序您可以考慮在清單中尋求更多的資源,其中largeHeapDocumentation

+0

RecyclerView真的能解決我的內存問題還是它只是一個ListViewAdapter的新實現? – confile

+0

RecyclerView看起來像一個ListView,但它是一個不同的動物。根據谷歌和我的測試到目前爲止,是更有效的,然後ListViews。雖然,我不能向你保證這將解決你的OOM問題。它將更好地回收視圖,並且工作更順利。但是,正如我所說的,在Android中加載圖片可能會非常棘手。 –

+0

@confile閱讀你的錯誤,我認爲你的問題是你的佔位符圖像。我會編輯我的答案。 –

相關問題