Renaud Favier
Renaud Favier

Reputation: 401

outOfMemoryError in a gallery activity

the code is commented for explanation, basicly i fill a gallery with downloaded images, but when the downloading finishes, the activity continues to think until outOfMemoryErrors comes 20sec later. and my images are never displayed :

public class PhotoDetailsActivity extends Activity {

    private MultimediaJson.PhotoCategory photoCategory;
    private int position;
    private Gallery gallery;
    private ImageManager im;
    private ArrayList<PhotoData> photos;
    private ArrayList<ImageView> ivArray;

    private LayoutInflater inflater;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.photo_detail_layout);

        inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);


        im = new Utils().new ImageManager();

        //I get the Images i've got to display from my intent
        photoCategory = (PhotoCategory) getIntent().getSerializableExtra(
                "photoDetails");
        //position is the image i've got to put the focus on
        position = (int) getIntent().getIntExtra("position", 1);

        //photoData is an arrayList of photo objects (containing the link)
        photos = photoCategory.photoData;


        ivArray = new ArrayList<ImageView>();
        gallery = (Gallery) findViewById(R.id.photoDetailGallery);

        //photo_detail_list_view_item is for the moment just an ImageView matching parent
        final PhotoAdapter pa = new PhotoAdapter(this,
                R.layout.photo_detail_list_view_item, ivArray);

        gallery.setAdapter(pa);

        //here is my downloading thread
        new Thread(new Runnable() {

            @Override
            public void run() {
                // for tests, will be pos<photos.size()
                for (int pos = 0; pos < 2; pos++) {
                    final ImageView imageView = new ImageView(getBaseContext());
                    imageView.setImageBitmap(im.downloadFromUrl(
                            photos.get(pos).photo.link,
                            photos.get(pos).photo.md5));
                    ivArray.add(imageView);

                    //adding the last photo to my adapter and notify it
                    runOnUiThread(new Runnable() {

                        @Override
                        public void run() {
                            if (ivArray != null && ivArray.size() > 0) {
                                pa.notifyDataSetChanged();
                                pa.add(ivArray.get(ivArray.size()-1));
                            }
                            pa.notifyDataSetChanged();
                        }
                    });

                }

            }
        }).start();

    }

my Adapter :

private class PhotoAdapter extends ArrayAdapter<ImageView> {

        ArrayList<ImageView> imageViews;

        public PhotoAdapter(Context context, int textViewResourceId,
                ArrayList<ImageView> images) {
            super(context, textViewResourceId, images);
            imageViews = images;
        }

        public boolean isEnabled(int position) {
            return false;
        }

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

            if (convertView == null) {
                convertView = inflater.inflate(
                        R.layout.photo_detail_list_view_item, null);
            }
            final ImageView iv = imageViews.get(position);
            if (iv != null) {
                ImageView iv2 = (ImageView) convertView
                        .findViewById(R.id.photo_detail_list_view_image_view);
                iv2 = iv;
            }

            return convertView;
        }

    }

and my log cat :

03-01 10:44:20.343: I/renaud(8553): downloadFromUrl begin
03-01 10:44:20.343: I/renaud(8553): imageFileCreated
03-01 10:44:20.343: I/renaud(8553): imageFile do exists //my images are well download there
03-01 10:44:20.484: D/dalvikvm(8553): GC_EXTERNAL_ALLOC freed 74K, 40% free 5106K/8455K, external 4970K/5134K, paused 25ms
03-01 10:44:21.074: D/dalvikvm(8553): GC_CONCURRENT freed 1832K, 45% free 5290K/9607K, external 5830K/6207K, paused 2ms+3ms
03-01 10:44:21.472: D/dalvikvm(8553): GC_FOR_MALLOC freed 1699K, 44% free 5405K/9607K, external 4970K/6207K, paused 30ms
03-01 10:44:21.855: D/dalvikvm(8553): GC_FOR_MALLOC freed 1726K, 44% free 5578K/9799K, external 4970K/6207K, paused 32ms
03-01 10:44:21.855: I/dalvikvm-heap(8553): Grow heap (frag case) to 13.435MB for 794336-byte allocation
03-01 10:44:21.890: D/dalvikvm(8553): GC_FOR_MALLOC freed 517K, 46% free 5836K/10631K, external 4970K/6207K, paused 25ms
03-01 10:44:22.578: D/dalvikvm(8553): GC_CONCURRENT freed 2010K, 45% free 5899K/10631K, external 4970K/6207K, paused 2ms+8ms
03-01 10:44:22.601: D/dalvikvm(8553): GC_FOR_MALLOC freed 62K, 46% free 5836K/10631K, external 4970K/6207K, paused 26ms
03-01 10:44:22.605: I/dalvikvm-heap(8553): Grow heap (frag case) to 14.067MB for 1191496-byte allocation
03-01 10:44:22.644: D/dalvikvm(8553): GC_FOR_MALLOC freed 775K, 48% free 6224K/11847K, external 4970K/6207K, paused 27ms
03-01 10:44:23.249: D/dalvikvm(8553): GC_CONCURRENT freed 2034K, 48% free 6238K/11847K, external 4970K/6207K, paused 1ms+16ms
03-01 10:44:23.546: D/dalvikvm(8553): GC_FOR_MALLOC freed 1073K, 48% free 6224K/11847K, external 4970K/6207K, paused 35ms
03-01 10:44:23.546: I/dalvikvm-heap(8553): Grow heap (frag case) to 15.013MB for 1787236-byte allocation
03-01 10:44:23.589: D/dalvikvm(8553): GC_FOR_MALLOC freed 1163K, 51% free 6806K/13639K, external 4970K/6207K, paused 31ms
03-01 10:44:24.191: D/dalvikvm(8553): GC_CONCURRENT freed 2038K, 51% free 6816K/13639K, external 4970K/6207K, paused 2ms+14ms
03-01 10:44:24.773: D/dalvikvm(8553): GC_CONCURRENT freed 2057K, 51% free 6806K/13639K, external 4970K/6207K, paused 2ms+17ms
03-01 10:44:24.960: D/dalvikvm(8553): GC_FOR_MALLOC freed 566K, 51% free 6806K/13639K, external 4970K/6207K, paused 37ms
03-01 10:44:24.964: I/dalvikvm-heap(8553): Grow heap (frag case) to 16.434MB for 2680844-byte allocation
03-01 10:44:25.011: D/dalvikvm(8553): GC_FOR_MALLOC freed 1745K, 44% free 7678K/13639K, external 4970K/6207K, paused 37ms
03-01 10:44:25.152: D/dalvikvm(8553): GC_CONCURRENT freed 173K, 44% free 7732K/13639K, external 4970K/6207K, paused 2ms+20ms
03-01 10:44:25.742: D/dalvikvm(8553): GC_CONCURRENT freed 2101K, 44% free 7678K/13639K, external 4970K/6207K, paused 2ms+20ms
03-01 10:44:26.339: D/dalvikvm(8553): GC_CONCURRENT freed 2048K, 44% free 7678K/13639K, external 4970K/6207K, paused 2ms+22ms
03-01 10:44:26.945: D/dalvikvm(8553): GC_CONCURRENT freed 2048K, 44% free 7678K/13639K, external 4970K/6207K, paused 2ms+23ms
03-01 10:44:27.167: D/dalvikvm(8553): GC_FOR_MALLOC freed 623K, 44% free 7678K/13639K, external 4970K/6207K, paused 45ms
03-01 10:44:27.175: I/dalvikvm-heap(8553): Grow heap (frag case) to 18.564MB for 4021256-byte allocation
03-01 10:44:27.234: D/dalvikvm(8553): GC_FOR_MALLOC freed 2618K, 49% free 8987K/17607K, external 4970K/6207K, paused 47ms
03-01 10:44:27.406: D/dalvikvm(8553): GC_CONCURRENT freed 210K, 49% free 9020K/17607K, external 4970K/6207K, paused 1ms+28ms
03-01 10:44:28.019: D/dalvikvm(8553): GC_CONCURRENT freed 2080K, 49% free 8987K/17607K, external 4970K/6207K, paused 2ms+29ms
03-01 10:44:28.640: D/dalvikvm(8553): GC_CONCURRENT freed 2047K, 49% free 8987K/17607K, external 4970K/6207K, paused 2ms+30ms
03-01 10:44:29.261: D/dalvikvm(8553): GC_CONCURRENT freed 2048K, 49% free 8987K/17607K, external 4970K/6207K, paused 1ms+32ms
03-01 10:44:29.878: D/dalvikvm(8553): GC_CONCURRENT freed 2047K, 49% free 8987K/17607K, external 4970K/6207K, paused 2ms+33ms
03-01 10:44:30.503: D/dalvikvm(8553): GC_CONCURRENT freed 2048K, 49% free 8987K/17607K, external 4970K/6207K, paused 2ms+35ms
03-01 10:44:30.558: D/dalvikvm(8553): GC_FOR_MALLOC freed 5K, 49% free 8987K/17607K, external 4970K/6207K, paused 51ms
03-01 10:44:30.570: I/dalvikvm-heap(8553): Grow heap (frag case) to 21.760MB for 6031876-byte allocation
03-01 10:44:30.640: D/dalvikvm(8553): GC_FOR_MALLOC freed 3927K, 54% free 10951K/23559K, external 4970K/6207K, paused 59ms
03-01 10:44:30.839: D/dalvikvm(8553): GC_CONCURRENT freed 248K, 54% free 10975K/23559K, external 4970K/6207K, paused 2ms+45ms
03-01 10:44:31.511: D/dalvikvm(8553): GC_CONCURRENT freed 2072K, 54% free 10951K/23559K, external 4970K/6207K, paused 2ms+42ms
03-01 10:44:32.234: D/dalvikvm(8553): GC_CONCURRENT freed 2047K, 54% free 10951K/23559K, external 4970K/6207K, paused 2ms+43ms
03-01 10:44:32.933: D/dalvikvm(8553): GC_CONCURRENT freed 2047K, 54% free 10951K/23559K, external 4970K/6207K, paused 2ms+45ms
03-01 10:44:33.613: D/dalvikvm(8553): GC_CONCURRENT freed 2048K, 54% free 10951K/23559K, external 4970K/6207K, paused 2ms+45ms
03-01 10:44:34.261: D/dalvikvm(8553): GC_CONCURRENT freed 2047K, 54% free 10951K/23559K, external 4970K/6207K, paused 1ms+47ms
03-01 10:44:34.945: D/dalvikvm(8553): GC_CONCURRENT freed 2047K, 54% free 10951K/23559K, external 4970K/6207K, paused 2ms+48ms
03-01 10:44:35.636: D/dalvikvm(8553): GC_CONCURRENT freed 2047K, 54% free 10951K/23559K, external 4970K/6207K, paused 2ms+50ms
03-01 10:44:36.019: D/dalvikvm(8553): GC_FOR_MALLOC freed 1113K, 54% free 10951K/23559K, external 4970K/6207K, paused 85ms
03-01 10:44:36.019: I/dalvikvm-heap(8553): Forcing collection of SoftReferences for 9047804-byte allocation
03-01 10:44:36.089: D/dalvikvm(8553): GC_FOR_MALLOC freed <1K, 54% free 10951K/23559K, external 4970K/6207K, paused 69ms
03-01 10:44:36.089: E/dalvikvm-heap(8553): Out of memory on a 9047804-byte allocation.
03-01 10:44:36.089: I/dalvikvm(8553): "main" prio=5 tid=1 RUNNABLE
03-01 10:44:36.089: I/dalvikvm(8553):   | group="main" sCount=0 dsCount=0 obj=0x4001f188 self=0xce60
03-01 10:44:36.089: I/dalvikvm(8553):   | sysTid=8553 nice=0 sched=0/0 cgrp=default handle=-1345006528
03-01 10:44:36.089: I/dalvikvm(8553):   at java.util.ArrayList.add(ArrayList.java:~123)
03-01 10:44:36.089: I/dalvikvm(8553):   at android.widget.ArrayAdapter.add(ArrayAdapter.java:178)
03-01 10:44:36.089: I/dalvikvm(8553):   at com.blablabla.PhotoDetailsActivity$1$1.run(PhotoDetailsActivity.java:77)
03-01 10:44:36.089: I/dalvikvm(8553):   at android.os.Handler.handleCallback(Handler.java:587)
03-01 10:44:36.089: I/dalvikvm(8553):   at android.os.Handler.dispatchMessage(Handler.java:92)
03-01 10:44:36.089: I/dalvikvm(8553):   at android.os.Looper.loop(Looper.java:130)
03-01 10:44:36.089: I/dalvikvm(8553):   at android.app.ActivityThread.main(ActivityThread.java:3683)
03-01 10:44:36.089: I/dalvikvm(8553):   at java.lang.reflect.Method.invokeNative(Native Method)
03-01 10:44:36.089: I/dalvikvm(8553):   at java.lang.reflect.Method.invoke(Method.java:507)
03-01 10:44:36.089: I/dalvikvm(8553):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
03-01 10:44:36.089: I/dalvikvm(8553):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
03-01 10:44:36.089: I/dalvikvm(8553):   at dalvik.system.NativeStart.main(Native Method)
03-01 10:44:36.089: D/AndroidRuntime(8553): Shutting down VM
03-01 10:44:36.089: W/dalvikvm(8553): threadid=1: thread exiting with uncaught exception (group=0x40015560)
03-01 10:44:36.101: E/AndroidRuntime(8553): FATAL EXCEPTION: main
03-01 10:44:36.101: E/AndroidRuntime(8553): java.lang.OutOfMemoryError
03-01 10:44:36.101: E/AndroidRuntime(8553):     at java.util.ArrayList.add(ArrayList.java:123)
03-01 10:44:36.101: E/AndroidRuntime(8553):     at android.widget.ArrayAdapter.add(ArrayAdapter.java:178)
03-01 10:44:36.101: E/AndroidRuntime(8553):     at com.blablabla.PhotoDetailsActivity$1$1.run(PhotoDetailsActivity.java:77)
03-01 10:44:36.101: E/AndroidRuntime(8553):     at android.os.Handler.handleCallback(Handler.java:587)
03-01 10:44:36.101: E/AndroidRuntime(8553):     at android.os.Handler.dispatchMessage(Handler.java:92)
03-01 10:44:36.101: E/AndroidRuntime(8553):     at android.os.Looper.loop(Looper.java:130)
03-01 10:44:36.101: E/AndroidRuntime(8553):     at android.app.ActivityThread.main(ActivityThread.java:3683)
03-01 10:44:36.101: E/AndroidRuntime(8553):     at java.lang.reflect.Method.invokeNative(Native Method)
03-01 10:44:36.101: E/AndroidRuntime(8553):     at java.lang.reflect.Method.invoke(Method.java:507)
03-01 10:44:36.101: E/AndroidRuntime(8553):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
03-01 10:44:36.101: E/AndroidRuntime(8553):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
03-01 10:44:36.101: E/AndroidRuntime(8553):     at dalvik.system.NativeStart.main(Native Method)

here is my NEW ImageManager :

    public class ImageManager {

    public Bitmap downloadFromUrl(String imageURL, String fileName) {
        try {
            Log.i("renaud", "downloadFromUrl begin");
            final String extStorageDirectory = Environment
                    .getExternalStorageDirectory().toString();
            final String festivalDirectory_path = extStorageDirectory
                    + Constants.IMAGES_STORAGE_PATH;
            File imageOutputFile = new File(festivalDirectory_path, "/");
            if (imageOutputFile.exists() == false) {
                imageOutputFile.mkdirs();
            }
            File imageFile = new File(imageOutputFile, fileName);
            Log.i("renaud", "imageFileCreated");
            if (!imageFile.exists()) {
                Log.i("renaud", "imageFile do not exists");
                URL url = new URL(imageURL);
                HttpURLConnection urlConnection;
                urlConnection = (HttpURLConnection) url.openConnection();

                urlConnection.setRequestMethod("GET");
                urlConnection.setDoOutput(true);
                urlConnection.connect();

                FileOutputStream fileOutput = new FileOutputStream(
                        imageFile);
                InputStream inputStream = urlConnection.getInputStream();
                byte[] buffer = new byte[1024];
                int bufferLength = 0;
                while ((bufferLength = inputStream.read(buffer)) > 0) {
                    fileOutput.write(buffer, 0, bufferLength);
                }

                fileOutput.close();
                Log.i("renaud", "image stored");
                return decodeFile(imageFile.getAbsoluteFile());
            } else {
                Log.i("renaud", "imageFile do exists");
                Bitmap bm = decodeFile(imageFile.getAbsoluteFile());
                if (bm == null) {
                    imageFile.delete();
                    return null;
                }
                return bm;
            }

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}

 private Bitmap decodeFile(File f) {
        try {
            // Decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(f), null, o);

            // The new size we want to scale to
            final int REQUIRED_SIZE = 150;

            // Find the correct scale value. It should be the power of 2.
            int width_tmp = o.outWidth, height_tmp = o.outHeight;
            int scale = 1;
            while (true) {
                if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)
                    break;
                width_tmp /= 2;
                height_tmp /= 2;
                scale *= 2;
            }

            // Decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize = scale;
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);

        } catch (FileNotFoundException e) {
        }
        return null;
    }

Upvotes: 0

Views: 544

Answers (1)

Maneesh
Maneesh

Reputation: 6128

One thing you should always notices that you will rarely got out of memory while downloading data. Out of memory is always related to when you are converting inputstream to bitmap. So foucs the code where you are converting downloaded inputstream to bitmap. Below is the code to check and shrink the size of bitmap to avoid out of memory

try
{
img_t.setImageBitmap(btm);

}
 catch(OutOfMemoryError e)
         {

             set_photo_in_imageview(is,getRealPathFromURI(selectedImageUri));
             txt_has_data=true;
         }

private void set_photo_in_imageview(InputStream is,String path_name)
{
    BitmapFactory.Options options=new BitmapFactory.Options();
    options.inSampleSize = 8;
    options.inJustDecodeBounds = true;

    Bitmap preview_bitmap=BitmapFactory.decodeStream(is,null,options);

    final int REQUIRED_SIZE=70;

    int width_tmp=options.outWidth, height_tmp=options.outHeight;
    int scale=1;
    while(true){
        if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
            break;
        width_tmp/=2;
        height_tmp/=2;
        scale*=2;
    }

    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize=scale;
    Bitmap btm=BitmapFactory.decodeStream(is, null, o2);
    img_t.setImageBitmap(btm);
    txt_photo_id.setVisibility(TextView.VISIBLE);
    String any[]=path_name.split("/");
    if(any.length==0)
    {
        txt_photo_id.setText(path_name);
    }
    else
    {
        txt_photo_id.setText(any[any.length-1]);    
    }
    //txt_photo_id.setText(path_name);
}

Upvotes: 1

Related Questions