Question

I'm trying to retrieve all the images from the sdcard0 by using adapter - getView() method. I'm trying to populate a gallery view, which is deprecated but the requirements document imply that I use gallery view. As i see, if there are very few images then this approach works but if a number like more than 10 or so images on sdcard0 then I get OutOfMemoryException. Can someone help me to reuse the memory for Bitmap object that I'm reading from file and creating

"Bitmap bitmap = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile((file.getPath())), 275, 210);".

Since I'm creating a lot of Bitmap objects I'm running out of memory. The images are all of jpg format, clicked using the on device camera and size averaging at 3.5 MB. Its a Samsung Galaxy S4 on which i'm testing.

Button btnFetch;
ImageView ivLoad;
Gallery galView;
MyAdapter adapter;
static Context context;
File[] files;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_sdcard);
    context = SDCardActivity.this;
    btnFetch = (Button) findViewById(R.id.btnFetch);
    ivLoad = (ImageView) findViewById(R.id.ivLoad);
    galView = (Gallery) findViewById(R.id.galView);

    loadingMyGalleryView();
    adapter = new MyAdapter();
    galView.setAdapter(adapter);

    galView.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {

            File file = files[position];
            Bitmap bm = BitmapFactory.decodeFile(file.getPath());
            ivLoad.setImageBitmap(bm);
        }
    });
}

private void loadingMyGalleryView() {
    if (android.os.Environment.getExternalStorageState().equals(
            android.os.Environment.MEDIA_MOUNTED)) {

        // It have to be matched with the directory in SDCard
        File f = new File(Environment.getExternalStorageDirectory()
                + File.separator + "DCIM/Camera");
        boolean exist = f.exists();
        Log.d("loki", "Reached Line 80" + exist);
        if (exist) {
            Log.d("loki", "Reached line 82");
            files = f.listFiles();
            for (int i = 0; i < files.length; i++) {
                Log.d("loki", "" + files[i]);
            }
        }
    }
}

class MyAdapter extends BaseAdapter {

    @Override
    public Object getItem(int position) {
        return files[position];
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getCount() {
        // Log.d("loki", ""+files.length);
        return files.length;

    }

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

        ImageView image = new ImageView(context);
        File file = files[position];
        Bitmap bitmap = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile((file.getPath())), 275, 210);
        image.setImageBitmap(bitmap);
        image.setAdjustViewBounds(true);
        image.setScaleType(ImageView.ScaleType.FIT_CENTER);
        return image;
    }
}

LogCat shows:

08-10 12:15:38.403: E/AndroidRuntime(21585): FATAL EXCEPTION: main
08-10 12:15:38.403: E/AndroidRuntime(21585): java.lang.OutOfMemoryError
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:529)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:302)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:328)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at com.example.sdcard.SDCardActivity$MyAdapter.getView(SDCardActivity.java:140)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.widget.AbsSpinner.onMeasure(AbsSpinner.java:193)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.View.measure(View.java:15518)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:681)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.View.measure(View.java:15518)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4825)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.View.measure(View.java:15518)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.widget.LinearLayout.measureVertical(LinearLayout.java:847)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.View.measure(View.java:15518)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4825)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2313)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.View.measure(View.java:15518)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1874)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1089)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1265)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:989)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4351)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.Choreographer.doCallbacks(Choreographer.java:562)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.Choreographer.doFrame(Choreographer.java:532)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.os.Handler.handleCallback(Handler.java:725)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.os.Handler.dispatchMessage(Handler.java:92)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.os.Looper.loop(Looper.java:137)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.app.ActivityThread.main(ActivityThread.java:5195)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at java.lang.reflect.Method.invokeNative(Native Method)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at java.lang.reflect.Method.invoke(Method.java:511)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at dalvik.system.NativeStart.main(Native Method)
Was it helpful?

Solution

Your adapter is broken as you do not correctly handle convertView (if fact you do nothing here) therefore for each row you create new view instead of reusing existing ones which consumes memory. I.e.:

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

    View v = convertView;

    if(v == null){
       // Inflate View from xml or create by code
       v = .....
    }

    // display your thumbnail
    ....
}

Here is reading: http://android-decoded.blogspot.com/2011/12/so-what-exactly-is-convertview.html

OTHER TIPS

In getView() reuse the second argument i.e convertView to save the memory for your application. to read more documentation click here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top