2015-10-07 139 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阅读你的错误,我认为你的问题是你的占位符图像。我会编辑我的答案。 –

相关问题