5

Possible Duplicate:
java.lang.OutOfMemoryError: bitmap size exceeds VM budget - Android

I used ViewPager to show set of images from resource folder , if my images was small in size every thing works fine ,

but when i replace it with high definition images which i need it to be in my app , it gave me this error :

java.lang.OutOfMemoryError: bitmap size exceeds VM budget

note 1 :

i have now 5 images in my code for testing but finally i will have around 30 high definition images ,

note 2 :

i wonder why this happen , i am new to android and first time to use viewpager class , before i used gallery class in another app with more than 30 high definition images and no exception happend .

any advice will be appreciated , thanks alot

my code :

logcat stack:

   FATAL EXCEPTION: main
    java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:563)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:439)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:462)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:488)
at com.test.demo.MyPagerAdapter.<init>(MyPagerAdapter.java:42)
at com.test.demo.MainActivity.onCreate(MainActivity.java:15)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
at android.app.ActivityThread.access$1500(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3687)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)

MainActivity

 public class MainActivity extends Activity {  
  private ViewPager mMyPager;
  private MyPagerAdapter mMyPagerAdapter;

public void onCreate(Bundle savedInstanceState) {   
  super.onCreate(savedInstanceState);   
    setContentView(R.layout.main);   

  mMyPager = (ViewPager) findViewById(R.id.mypages);           
  mMyPagerAdapter = new MyPagerAdapter(this);   
  mMyPager.setAdapter(mMyPagerAdapter);  }} 

MyPagerAdapter

  public class MyPagerAdapter extends PagerAdapter {   

    private ArrayList<ImageView> mViewsList;   
private Context mContext = null;   

public MyPagerAdapter(Context context) {   
    mContext = context;   
    mViewsList = new ArrayList<ImageView>();   

    Resources resource = mContext.getResources();   
   Bitmap bMap1 = BitmapFactory.decodeResource(resource,   
            R.drawable.one);   
   ImageView image1 = new ImageView(mContext);   
    image1.setImageBitmap(bMap1);      
    mViewsList.add(image1);   

    Bitmap bMap2 = BitmapFactory.decodeResource(resource,   
            R.drawable.two );   
    ImageView image2 = new ImageView(mContext);   
    image2.setImageBitmap(bMap2);      
    mViewsList.add(image2);   

    Bitmap bMap3 = BitmapFactory.decodeResource(resource,   
            R.drawable.three);   
   ImageView image3 = new ImageView(mContext);   
    image3.setImageBitmap(bMap3);      
    mViewsList.add(image3); 

    Bitmap bMap4 = BitmapFactory.decodeResource(resource,   
            R.drawable.four);   
   ImageView image4 = new ImageView(mContext);   
    image4.setImageBitmap(bMap4);      
    mViewsList.add(image4); 

    Bitmap bMap5 = BitmapFactory.decodeResource(resource,   
            R.drawable.five);   
   ImageView image5 = new ImageView(mContext);   
    image5.setImageBitmap(bMap5);      
    mViewsList.add(image5); 
               }      

@Override  
public int getCount() {   
    return mViewsList.size();   
                        }   

@Override  
public Object instantiateItem(View view, int position) {   
    View myView = mViewsList.get(position);   
    ((ViewPager) view).addView(myView);   
    return myView;   
              }   

@Override  
public boolean isViewFromObject(View view, Object object) {   
    return view == object;   
                  }   

@Override  
public void destroyItem(View view, int arg1, Object object) {   
    ((ViewPager) view).removeView((ImageView) object);   
                }   
                   }  
Community
  • 1
  • 1
androidqq6
  • 1,526
  • 2
  • 22
  • 47
  • Do you see this column on the right side of StackOverflow, next to your question, entitled "Related". Do you see this bunch of duplicates there? If so, go and lurk there. And master your search skills too please... – Marcin Orlowski Nov 23 '12 at 23:24
  • @WebnetMobile.com i saw that post before i post my question , but im new to android and first time to use viewpager class ,would you please explain to me why this happen is it related to viewpager class or bitmap , coz i used before gallery class in another app with more 30 high definition large size images and nothing happen ,thanks – androidqq6 Nov 23 '12 at 23:31

3 Answers3

4

Your Adaptor should not be written the way you have it. You should only be decoding the bitmaps in the instantiateItem method.

private Context context;
private ArrayList<Integer> mResourceList;
private Resources resource;  

public MyPagerAdapter(Context context) { 
    this.context = context;

    resource = context.getResources();

    mResourceList = new ArrayList<Integer>();     
    mResourceList.add(R.drawable.one);
    mResourceList.add(R.drawable.two);
    mResourceList.add(R.drawable.three);
    mResourceList.add(R.drawable.four);
    mResourceList.add(R.drawable.five);
}

@Override  
public Object instantiateItem(View view, int position) {   
        ImageView myView = new ImageView(context);

        Bitmap bitmap = BitmapFactory.decodeResource(resource, mResourceList.get(position) );
        myView.setImageBitmap(bitmap);

        ((ViewPager) view).addView(myView);   
        return myView;   
}   

Now, you need to make sure that your bitmaps are not exceeding the max size value (2048px x 2048px).

If you are, you must scale your image down. This can be done by adding a BitmapFactory.Options object to your BitmapFactory.decodeResouce parameters and setting the inSampleSize by a power of 2. Setting it by 2 will sample it down to 50%, 4 to 25%, etc.

BitmapFactory.Options options = new BitmapFactory.Options()
options.inSampleSize = 2

Bitmap bitmap = BitmapFactory.decodeResource(resource, mResouceList.get(position), options );

Hope this helped!

wdziemia
  • 1,429
  • 1
  • 14
  • 19
  • i used your code the images appear , then i scroll first image and secound image till now ok but when i scroll third image it force close with this exception again : java.lang.OutOfMemoryError: bitmap size exceeds VM budget any advice , thanks – androidqq6 Nov 24 '12 at 08:36
  • its 4000*2000 around size 4.5mb each image – androidqq6 Nov 24 '12 at 23:01
  • maybe i implement your code in wrong way , i have no experiance please help me another thing i used before larger images in gallery class and no problem happen why my dear – androidqq6 Nov 25 '12 at 11:30
  • Your images are WAY too big. Try to get them down to about 2000 x 500 and see if this solves your problem. – wdziemia Nov 25 '12 at 23:18
  • pleasee take alook on my new post after i try to scalled down the image thanks, http://stackoverflow.com/questions/13553610/large-image-from-resource-get-exception – androidqq6 Nov 25 '12 at 23:24
0

Size of your bitmap is very large,So try to scale your bitmap before loading it. Syntax for scaling bitmap

Bitmap bitmapName= Bitmap.createScaledBitmap(sourceBitmap, width, height,
                        true);

Where width and height are the size you want for the image to be.

Ravinder
  • 143
  • 1
  • 9
0

Your issue is that you're creating a bunch of bitmaps before really needing to.

Inside your instantiateView method, create the ImageView's and load the bitmaps and set them there. If you need, use your ArrayList to hold your resource ints to know which images to load if you need. This way, garbage collection will remove bitmaps as needed, and shouldn't cause memory issues.

DavidAndroidDev
  • 2,371
  • 3
  • 25
  • 41
  • as i mentioned in my above comment im new to android and first time to use both viewpager and bitmap so please can you provide your answer in code ,thanks – androidqq6 Nov 24 '12 at 08:28