78126

Memory-Leaks Image-Gallery Android - How can other applications handle it?

Question:

i'm trying to implement a image gallery, which should show ~ 5-15 smaller images and one "current selected" bigger image.

It looks like: <a href="http://www.mobisoftinfotech.com/blog/wp-content/uploads/2012/06/galleryDemo.png" rel="nofollow">http://www.mobisoftinfotech.com/blog/wp-content/uploads/2012/06/galleryDemo.png</a>

I've looked up many sources and now decided to use a bitmap-cache (lru-cache) (thanks to a person from this forum!).

I don't get memory-leaks at the moment, but i'm not happy with this solution because everytime i scroll, some images are removed from the cache and i've to reload them... so the user has to wait for reloading images... It's really annoying to wait 0.5 - 1 second every time i scroll to the other side...

public static WeakReference<Bitmap> getBitmap(String imageName, int width, int height) { if (!imageName.contains(".jpg")){ imageName += ".jpg"; } String pathToImage = getPathToImage(imageName); Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(pathToImage, options); /* * Calculate inSampleSize */ options.inSampleSize = calculateInSampleSize(options, width, height); /* * Removes the alpha-channel from bitmap (not necessary) */ options.inPreferredConfig = Bitmap.Config.RGB_565; /* * Decode bitmap with inSampleSize set */ options.inJustDecodeBounds = false; WeakReference<Bitmap> scaledBitmap = new WeakReference<Bitmap>( BitmapFactory.decodeFile(pathToImage, options)); return scaledBitmap;

Is it possible that i make a mistake in getting the images? At the moment i'll use 320x480 resolution for the single-selected image and 64x64 for the list on the bottom...

Really weird is the fact, that it doesn't matter, how big the resolutions of the images are, the lru-cache will still remove some images, even if i choose only 64x64 images... I might be doing wrong something with the lru cache?

The following code shows my implementation:

/* * Bitmaps which should be shown */ mMemoryCache = (BitmapCache) getLastNonConfigurationInstance(); if (mMemoryCache == null) { // Get max available VM memory, exceeding this amount will throw an // OutOfMemory exception. Stored in kilobytes as LruCache takes an // int in its constructor. final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); // Use 1/4th of the available memory for this memory cache. final int cacheSize = maxMemory / 2; // TODO default 8 mMemoryCache = new BitmapCache(cacheSize); }

And the Class BitmapCache:

public BitmapCache(int maxSize, Resources resources) { super(maxSize); this.resources = resources; } @Override protected int sizeOf(String key, AsyncDrawable value) { if (value.getBitmap() != null) { /* * The cache size will be measured in kilobytes rather than * number of items. */ return value.getBitmap().getRowBytes() * value.getBitmap().getHeight() / 1024; } return super.sizeOf(key, value); } public void loadBitmap(Picture picture, ImageView mImageView, ImageResolution resolution) { if (cancelPotentialWork(picture.getFileName(), // + resolution.name() mImageView)) { final BitmapWorkerTask task = new BitmapWorkerTask(this, mImageView, picture, resolution); final AsyncDrawable asyncDrawable = new AsyncDrawable(resources, null, task); mImageView.setImageDrawable(asyncDrawable); task.execute(); } }

Thank you very much :(

Some more code: BitmapWorkerTask:

@Override protected Bitmap doInBackground(Void... params) { /* * Decode image in background. */ final Bitmap bitmap = FileHandler.getBitmap( picture.getPictureId() + "", resolution).get(); return bitmap; } @Override protected void onPostExecute(Bitmap bitmap) { /* * Once complete, see if ImageView is still around and set bitmap. */ if (isCancelled()) { bitmap = null; } if (imageViewReference != null && bitmap != null) { final ImageView imageView = imageViewReference.get(); if (imageView != null) { final Drawable drawable = imageView.getDrawable(); if (drawable instanceof AsyncDrawable) { final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; final BitmapWorkerTask bitmapWorkerTask = asyncDrawable .getBitmapWorkerTask(); if (this == bitmapWorkerTask && imageView != null) { imageView.setImageBitmap(bitmap); bitmapCache.addBitmapToMemoryCache( picture.getFileName(), // + resolution.name() asyncDrawable); } } } } }

Answer1:

AWESOME! I found the mistake why it couldn't work. The fault was in my LruCache, which stored AsyncDrawables, what is totally dumb. Everytime sizeOf in the LruCache was called, the bitmap inside of the asyncdrawable was null, so he just returned super.sizeOf(key, value).

Now it works like a charm!! :)

Thanks for your helps!

Recommend

  • Image load in imageView from gallery become black
  • Android orientation issue on samsung devies with Exif
  • Problem with big images ( java.lang.OutOfMemoryError: bitmap size exceeds VM budget )
  • Get Image Width and Height from URI
  • Saving images to Parse
  • java.io.IOException: Is a directory Android
  • Android: Not able to call onActivityResult() method after capturing photo by camera
  • Why does my file not exist even when I gave it a path that exist?
  • Soft reference does not behave as expected on Android
  • BitmapFactory decode an BMP image
  • How to check whether an image is captured in portrait mode or landscape mode using camera in android
  • OutOFMemory error in volley library
  • Android image didn't display to ImageView from image URL
  • Graph matplotlib to show total count in the histogram bins
  • r - extract alphanumeric strings from text
  • How to get the position of a click event relative to its layer in KineticJS?
  • How to get or calculate size of Azure File/Share or Service
  • Migration tool for ANTLR grammar
  • How to model a mixture of finite components from different parametric families with JAGS?
  • Load image without autoscaling in Android
  • Updating one element of a bound Observable collection
  • Imageloader not loading image on real device
  • Greek letters in legend in R
  • SQL Server re-calculate or not?
  • Need a consistent TimePicker gizmo for mobile web site
  • Python: sending key press events over SSH
  • Receive mouse move even cursor is outside control
  • Error in making a socket connection
  • Switch to popup in python using selenium
  • How to define and use opencv mat of user type
  • Spring security and special characters
  • Deleting and Updating values from a cusrsor adapter
  • Modifying destination and filename of gulp-svg-sprite
  • 'TypeError' while using NSGA2 to solve Multi-objective prob. from pyopt-sparse in OpenMDAO
  • NSLayoutConstraint that would pin a view to the bottom edge of a superview
  • Bitwise OR returns boolean when one of operands is nil
  • sending mail using smtp is too slow
  • Busy indicator not showing up in wpf window [duplicate]
  • Why is Django giving me: 'first_name' is an invalid keyword argument for this function?
  • How can I use `wmic` in a Windows PE script?