views:

333

answers:

1

I have a list of 70 text items with image icons(which are stored in drawables folder). If I launch application the first time and scroll the list slowly - the exception doesn't occur.

When the application is launched the first time and I scroll the list with 'fling' action the following exception occurs:

java.lang.OutOfMemoryError: bitmap size exceeds VM budget
 at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
 at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:439)
 at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:322)
 at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:688)
 at android.content.res.Resources.loadDrawable(Resources.java:1710)
 at android.content.res.Resources.getDrawable(Resources.java:585)

After that, if I kill the application with DDMS, start it again and scroll it with 'fling' action, exception doesn't occur. So the exception arises only if application is installed and launched the first time.

Here is the adapter I use for the list:

public class AuthorAdapter extends ArrayAdapter<Author> {

private ArrayList<Author> items;
private Context context;
private LayoutInflater inflater;

public AuthorAdapter(Context context, int textViewResourceId, ArrayList<Author> items) {
    super(context, textViewResourceId, items);
    this.items = items;
    this.context = context;
    inflater = LayoutInflater.from(this.context);
}

static class ViewHolder {
    ImageView authorFace;
    TextView authorName;
    TextView authorWho;
}

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

    ViewHolder holder;

    if (convertView == null) {
        convertView = inflater.inflate(R.layout.autor_data, null);

        holder = new ViewHolder();
        holder.authorFace = (ImageView) convertView.findViewById(R.id.authorFaceImageView);
        holder.authorName = (TextView) convertView.findViewById(R.id.authorNameTextView);
        holder.authorWho = (TextView) convertView.findViewById(R.id.authorWhoTextView);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    Author author = items.get(position);
    if (author != null) {
        if (holder.authorFace != null) {
            String faceFileName = author.getFace();
            String facePlaceName = context.getPackageName() + ":drawable/" + faceFileName.subSequence(0, faceFileName.lastIndexOf("."));
            int faceFileId = context.getResources().getIdentifier(facePlaceName, null, null);
            holder.authorFace.setImageResource(faceFileId);
        }
        if (holder.authorName != null) {
            holder.authorName.setText(author.getName());
        }
        if (holder.authorWho != null) {
            holder.authorWho.setText(author.getWho());
        }
    }
    return convertView;
}

}

Is there a way to avoid the exception? Should I catch the exception and escape the memory somehow?

Any advice how to accomplish this?

Thanks.

+3  A: 

You can't catch a java.lang.OutOfMemoryError. They're pretty much fatal.

Now, you say the problem only occurs the first time you run your application. This makes me think that the problem isn't with the view code. If a user flings a resource heavy view it can use a lot of memory, but as you say, normally your application works fine.

So - what initialisation do you do the first time you run your application? Is it possible one of the first-time run-once tasks is leaking memory meaning that there isn't enough left to use your view?

Dave Webb
Actually I do not initialize any images when I first start the application. All my images are stored in the drawables folder. I only set the adapter for the list. In the getView() method of the adapter I set the image for each list item(see the code above):holder.authorFace.setImageResource(faceFileId);As I understand getView() method is called each time a list item is shown on the phone screen. Probably when I quickly scroll the list the cache doesn't have time to recycle.When I slowly scroll the list no exception is observed.
Zzokk
I was wondering if there's some other initialisation behaviour that's leaking memory so there's no room on the Heap for lots of images when you fast scroll your View. This would explain why the problem only occurs the first time you run your application.
Dave Webb
Agree with Dave, i'd start to look on what are you doing first time you start the app vs normal startup. You're holding to something big during your first init of the app.
Alex Volovoy
Thanks for the help. I do use background and button images in the activity that precedу my list activity. Though I initialize them in my xml layout. Do I have to unbind them according to http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html ?Can anyone give a working example on how to deal with heavy images set as activity background?
Zzokk