title: Out of memory + Bitmap + ImageView + ViewPager
body: <p>I'm working on a simple <strong>photo gallery</strong> for my app. But I'm having some really annoying <strong>memory leaks</strong>, and I don't know how to handle them.</p>
  
  <p>Can you guys help me? I've search in other question but, according to the answers, I seem to be doing things right. Of course, I'm not.</p>
  
  <p><strong>My code:</strong></p>
  
  <p>I'm using <a href="https://github.com/MikeOrtiz/TouchImageView" rel="nofollow"><code>TouchImageView</code></a> to show the images.</p>
  
  <p>Also, I have extended <code>ViewPager</code> to support the zoom function, like this:</p>
  
  <pre><code>public class ExtendedViewPager extends ViewPager {
  
      public ExtendedViewPager(Context context) {
          super(context);
      }
  
      public ExtendedViewPager(Context context, AttributeSet attrs) {
          super(context, attrs);
      }
  
      @Override
      protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
          if (v instanceof TouchImageView) {
              /*
              canScrollHorizontally is not supported for Api &lt; 14. To get around this issue,
              ViewPager is extended and canScrollHorizontallyFroyo, a wrapper around
              canScrollHorizontally supporting Api &gt;= 8, is called.
              */
              return ((TouchImageView) v).canScrollHorizontallyFroyo(-dx);
          } else {
              return super.canScroll(v, checkV, dx, x, y);
          }
      }
  }
  </code></pre>
  
  <p>Some of this photos may be big (like 2000x2000px, for example). So I <code>resample</code> them before adding them to the view, using this resample function:</p>
  
  <pre><code>public static Bitmap resample(int resourceID, boolean toFullScreen, Context c){
          //set the width and height we want to use as maximum display
          WindowManager wm = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
          Display display = wm.getDefaultDisplay();
          int targetWidth = display.getWidth();
          int targetHeight = display.getHeight();
  
          //create bitmap options to calculate and use sample size
          BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
  
          //first decode image dimensions only - not the image bitmap itself
          bmpOptions.inJustDecodeBounds = true;
          BitmapFactory.decodeResource(c.getResources(), resourceID, bmpOptions);
  
          //image width and height before sampling
          int currHeight = bmpOptions.outHeight;
          int currWidth = bmpOptions.outWidth;
  
          //variable to store new sample size
          int sampleSize = 1;
  
          //calculate the sample size if the existing size is larger than target size
          if (toFullScreen || currHeight &gt; targetHeight || currWidth &gt; targetWidth){
              //use either width or height
              if (toFullScreen || currWidth &gt; currHeight)
                  sampleSize = Math.round((float)currHeight / (float)targetHeight);
              else
                  sampleSize = Math.round((float)currWidth / (float)targetWidth);
          }
  
          //use the new sample size
          bmpOptions.inSampleSize = sampleSize;
          //now decode the bitmap using sample options
          bmpOptions.inJustDecodeBounds = false;
  
          //get the file as a bitmap and return it
          Bitmap pic = BitmapFactory.decodeResource(c.getResources(), resourceID, bmpOptions);
          return pic;
      }
  </code></pre>
  
  <p>And call in it on my <code>PagerAdapter</code> implementation, in which I also attempt to <code>recycle()</code> the bitmaps:</p>
  
  <pre><code>private class TouchImagePagerAdapter extends PagerAdapter {
      @Override
      public int getCount() {
          return galleryImages.length;
      }
  
      @Override
      public boolean isViewFromObject(View view, Object object) {
          return view == object;
      }
  
      @Override
      public Object instantiateItem(ViewGroup container, int position) {
          Context context = PhotoGalleryActivity.this;
          TouchImageView touchImageView = new TouchImageView(context);
          touchImageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
  
          touchImageView.setImageBitmap(Helper.resample(galleryImages[position].getImgResource(), false, getApplicationContext()));
          container.addView(touchImageView, 0);
  
          return touchImageView;
      }
  
      @Override
      public void destroyItem(ViewGroup collection, int position, Object object) {
          TouchImageView ti = (TouchImageView) object;
          BitmapDrawable bmpDrawable = (BitmapDrawable) ti.getDrawable();
          if (bmpDrawable != null) {
              Bitmap bmp = bmpDrawable.getBitmap();
              if(bmp != null &amp;&amp; !bmp.isRecycled())
                  bmp.recycle();
          }
          collection.removeView(ti);
          ti = null;
      }
  
      @Override
      public void destroyItem(View collection, int position, Object o) {
          View view = (View)o;
          ((ViewPager) collection).removeView(view);
          view = null;
      }
  }
  </code></pre>
  
  <p>Any clues?
  Thanks in advance.</p>