Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I created a ListView using an ArrayAdapter that implements the getView() method in this way:

public View getView(int position, View convertView, ViewGroup parent) {
    View rowView = convertView;
    if(rowView ==null){
    LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);         
    rowView = inflater.inflate(R.layout.rowlayout_member, parent, false);
            }
    TextView textView = (TextView) rowView.findViewById(R.id.label);
    TextView textView1 = (TextView) rowView.findViewById(R.id.label1);
    ImageView imageView = (ImageView) rowView.findViewById(R.id.icon);
    textView.setText(values[position]);
    textView1.setText(surname[position]);

    String s = values[position];
    if(foto[position] != null){
    Drawable c = Drawable.createFromPath(basePath+foto[position]);   // line 56 
    if(c!=null)
        imageView.setImageDrawable(c);
    else
        imageView.setImageResource(R.drawable.default);
    }else{
        imageView.setImageResource(R.drawable.default);                
    }
    return rowView;
}

All seems to work fine, but when I come in and go out to the List for many times(changing Activity) sometimes I obtain the following error:

08-06 15:06:14.110: E/dalvikvm-heap(3527): Out of memory on a 2380816-byte allocation.
08-06 15:06:14.110: W/dalvikvm(3527): threadid=1: thread exiting with uncaught exception (group=0x40a3d1f8)
08-06 15:06:14.120: E/AndroidRuntime(3527): FATAL EXCEPTION: main
08-06 15:06:14.120: E/AndroidRuntime(3527): java.lang.OutOfMemoryError
08-06 15:06:14.120: E/AndroidRuntime(3527):     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:299)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:324)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at android.graphics.drawable.Drawable.createFromPath(Drawable.java:880)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at host.framework.component.MySimpleArrayAdapter.getView(MySimpleArrayAdapter.java:56)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at android.widget.AbsListView.obtainView(AbsListView.java:2012)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at android.widget.ListView.makeAndAddView(ListView.java:1772)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at android.widget.ListView.fillUp(ListView.java:705)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at android.widget.ListView.fillGap(ListView.java:645)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at android.widget.AbsListView.trackMotionScroll(AbsListView.java:4546)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at android.widget.AbsListView$FlingRunnable.run(AbsListView.java:3813)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at android.os.Handler.handleCallback(Handler.java:605)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at android.os.Handler.dispatchMessage(Handler.java:92)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at android.os.Looper.loop(Looper.java:137)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at android.app.ActivityThread.main(ActivityThread.java:4424)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at java.lang.reflect.Method.invokeNative(Native Method)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at java.lang.reflect.Method.invoke(Method.java:511)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
08-06 15:06:14.120: E/AndroidRuntime(3527):     at dalvik.system.NativeStart.main(Native Method)
08-06 15:06:14.120: W/ActivityManager(149):   Force finishing activity host.activity/.ACT_CircoliDiSupporto
08-06 15:06:14.640: W/ActivityManager(149): Activity pause timeout for ActivityRecord{413de508 host.activity/.ACT_CircoliDiSupporto}
08-06 15:06:24.140: W/ActivityManager(149): Launch timeout has expired, giving up wake lock!
08-06 15:06:24.650: W/ActivityManager(149): Activity idle timeout for ActivityRecord{41389d58 host.activity/.HostActivity}

The line 56 (highlighted in the code) seems to generate the error

Drawable c = Drawable.createFromPath(basePath+foto[position]); 
share|improve this question
1  
Are you properly releasing the objects? Do not create drawables inside getView()... at least create it only once and re use that objects later on. – 66CLSjY yesterday
How can I be sure that my objects are correctly released? Uhm, maybe you are right: each time the getView is called a new Drawable is created. – Joseph82 yesterday
add comment (requires an account with 50 reputation)

2 Answers

up vote 1 down vote accepted

There are a number of problems with the current implementation:

  1. The code accesses and builds a Bitmap on the main/UI thread (Drawable c = Drawable.createFromPath(basePath+foto[position]); // line 56), this would make your list scrolling quite choppy
  2. A new drawable is created each time a view is requested, on 2.x Android systems it'll take a while for an unreferenced Bitmap to be collected by the Garbage Collector (GC), exacerbating the memory issue
  3. You load the image from storage without scaling it to the proper size, this may or may not be an issue since I don't know the dimension of the image you are displaying nor the dimension of the images

I would suggest you to use Universal Image Loader library (https://github.com/nostra13/Android-Universal-Image-Loader) which would solve all of the above issues. Though I am not sure if it provides native local image loading capability or if you have to extend some class to have such a capability.


[Edit]

I wouldn't recommend rolling your own solution as it'll take more time than you'd first imagined (trust me...). But if you really want to do it you can check out this tutorial: http://codehenge.net/blog/2011/06/android-development-tutorial-asynchronous-lazy-loading-and-caching-of-listview-images/

The above tutorial solves #1 & #2, for #3 check this: Strange out of memory issue while loading an image to a Bitmap object

share|improve this answer
Yes, you are right @Kai, my List is pretty choppy. Supposing I don't want use the Universal Loader library how can I deal with the problems you listed above? I suppose: 1) Create a separate thread that shold be interrupted if the item comes out of the scope of the list? 2) I can create a bitmap once, outside of getView? 3) I can scale all the image properly? Can this be acceptable? – Joseph82 yesterday
@Joseph82 updated answer, note that even the tutorial isn't really doing it right as it doesn't cancel the view's previous retrieve image operation, which would lead to "flashing image" artifects when scrolling very fast. So again I don't personally recommend this :P – Kai yesterday
Thank you @Kai. I think at first I'll try my solution: I like challenges :) But then I thin I will use the library that you suggest xD – Joseph82 yesterday
Good call. I was using my own AsyncTask to implement these functions, but had to fight a lot of bugs related to download-task-canceling and other issues until I realized now there are amazing image loading libs with less bugs and better functions. Certainly taught me a lesson on continuously checking the great StackOverflow for new libs/implementations/ideas. – Kai yesterday
Yes, surely it can be an opportunity to learn more about the Android world :) – Joseph82 23 hours ago
show 2 more commentsadd comment (requires an account with 50 reputation)

First of all you need a data structure like LruCache to hold the drawables that are being created.

How can I be sure that my objects are correctly released?

On activity destroy with usage the data structure, make sure the object of the class is being made null or clearing internal objects of it. (This will tell the gc that this object is ready to be cleared (in most cases)).

Also running a file operation on main thread is not the best approach as it will introduce jerkiness in listview scrolling. Try to do this in secondary thread.

share|improve this answer
Thank you @66CLSjY can you give me some example of how to use LruCache in ListView? – Joseph82 yesterday
Check out stackoverflow.com/questions/11623994/… and also research on Bitmap. – 66CLSjY yesterday
add comment (requires an account with 50 reputation)

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.