skip to Main Content

So I have an activity that is a gridview of HD images that are shrunk down to about 64×64 pixel boxes. I want to be able to get the image and then load them in the activity but I get an error that says that the Memory that it takes to load all of the pictures is a whole lot higher than the emulator/phone can handle.

I solved the problem by going into photoshop and making 64×64 images, but I’ve seen applications that run video and have hundreds of images in the current activity’s view. How do they compile with all of that memory in one listview?

I have another application that is a animation that plays a full screen animation with 20 pictures – but it has the same memory bound error in Android Studio.

How can I load 20 pictures on a single activity without getting a out of memory error.

Code for Activity with GridView
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.wallpapers);

    //**
    //Gridview, onclick of icon will open up dialog
    //allows to SAVE, SET, CANCEL - not in that order

    GridView gridview = (GridView) findViewById(R.id.gridview);
    gridview.setAdapter(new ImageAdapter(this));

    gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View v,
                                int position, long id) {
            Toast.makeText(Wallpaper.this, "Setting BG to ..." + position,
                    Toast.LENGTH_SHORT).show();
        }
    });
}

Code for ImageAdapter

public class ImageAdapter extends BaseAdapter {
private Context mContext;

public ImageAdapter(Context c) {
    mContext = c;
}

public int getCount() {
    return mThumbIds.length;
}

public Object getItem(int position) {
    return null;
}

public long getItemId(int position) {
    return 0;
}

// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
    ImageView imageView;
    if (convertView == null) {
        // if it's not recycled, initialize some attributes
        imageView = new ImageView(mContext);
        imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        imageView.setPadding(8, 8, 8, 8);
    } else {
        imageView = (ImageView) convertView;
    }

    imageView.setImageResource(mThumbIds[position]);
    return imageView;
}

// references to our images
private Integer[] mThumbIds = {
        R.raw.es_1_pix,  R.raw.es1_c, R.raw.es2_c, R.raw.es_1_pix
            //.raw.es_1_pix,R.raw.es_1_pix,R.raw.es_1_pix,R.raw.es_1_pix,R.raw.es_1_pix
        //R.raw.es2_c, R.raw.es3_c, R.raw.es4_c,
        //R.raw.es5_c, R.raw.es6_c, R.raw.es7_c
};
}

3

Answers


  1. There are a few things to consider.

    1. The easier solution – use image management library, the are plenty of those. All of them do the following things:

    Use WeakReference<Bitmap> everywhere instead of Bitmaps. WeakReference means System can clean images from the memory when there is not enough memory.

    If you display 20 64*64 images than make sure you do not store 20 1024*1024 images in memory, resize it to 64*64 either on runtime or outside of app.

    Generally speaking android can easily handle 20 average sized images(obviously not huge ones). If it rashes than there is something wrong with the code.

    UPDATE after the code was posted: the images you have in resource file are huge, scale it down and you should be fine.

    Login or Signup to reply.
  2. Not sure about the sound, but I know images need to use the Sample size with inJustDecodeBounds=true.

    public int calculateInSampleSize(BitmapFactory.Options options) {
    
            DisplayMetrics displayMetrics = cxt.getResources().getDisplayMetrics();
            int reqWidth = displayMetrics.widthPixels;
    
            final int height = options.outHeight;
            final int width = options.outWidth;
    
            double devCal2 =  (height*1000)/width;
            int reqHeight = (int) ((devCal2/1000)*reqWidth);
    
            int inSampleSize = 1;
    
            if (height > reqHeight || width > reqWidth) {
    
                final int halfHeight = height / 2;
                final int halfWidth = width / 2;
    
                // Calculate the largest inSampleSize value that is a power of 2 and keeps both
                // height and width larger than the requested height and width.
                while ((halfHeight / inSampleSize) > reqHeight
                        && (halfWidth / inSampleSize) > reqWidth) {
                    inSampleSize *= 2;
                }
            }
    
            return inSampleSize;
        }
    
        public Bitmap createBitmap(){
    
            BitmapFactory.Options options2 = new BitmapFactory.Options();
            options2.inJustDecodeBounds = true;
            options2.inDither=true;
            BitmapFactory.decodeFile(cxt.getExternalFilesDir(filepath) +"/companylogo.png",options2);
            options2.inSampleSize = calculateInSampleSize(options2);//=32
            options2.inJustDecodeBounds = false;
    
            return BitmapFactory.decodeFile(cxt.getExternalFilesDir(filepath) +"/companylogo.png",options2);
        }
    

    For reference please check http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

    Login or Signup to reply.
  3. If you really need the full HD image you could calculate how much space you need and load them into the views one by one replacing the others with a placeholder image. Then after loading one image make sure the system clean’s that image from memory. But like most people have said if its crashing from only 20 images it is probably something else.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search