I have a memory leak in my application that launches the GC several times and causes performance issues. I created a leak suspect report using MAT . Here is the report:
Problem Suspect 1: One instance of "android.graphics.Bitmap" loaded "occupies 4,194,368 (20,13%) bytes. The memory is accumulated in one instance of" byte [] "loaded by" ".
Problem Suspect 2: The class "android.content.res.Resources" loaded "occupies 3962,504 (19.02%) bytes. The memory is accumulated in one instance of" java.lang.Object [] "loaded by" ".
Problem Suspect 3: One instance of "android.graphics.Bitmap" loaded "occupies 3,145,792 (15,10%) bytes. The memory is accumulated in one instance of" byte [] "loaded by" ".
Judging by the reports, it is obvious that the memory leak is due to the bitmap. I researched a lot, but could not fix this leak. Please help me. I use a class ImageLoader to load and display bitmaps. To use this class, I simply call the displayImage() method. Here is the code:
public class ImageLoader { private static ImageLoader imageLoader; private int maxNoOfConnections = 4; FileCache fileCache; ExecutorService executorService; HttpURLConnection conn; InputStream is; OutputStream os; PhotosLoader photosLoader; Handler handler; Bitmap bitmap; private ImageLoader(Context context) { fileCache = new FileCache(context); executorService = Executors.newFixedThreadPool(maxNoOfConnections); handler = new Handler(); } public static ImageLoader getInstance(Context context) { if (imageLoader == null) imageLoader = new ImageLoader(context); return imageLoader; } public void displayImage(String url, ProgressBar pBar, ImageView imageView) { photosLoader = new PhotosLoader(url, imageView, pBar); executorService.submit(photosLoader); } private Bitmap getBitmap(String url) { File f = fileCache.getFile(url); bitmap = decodeFile(f); if (bitmap != null) return bitmap; try { URL imageUrl = new URL(url); conn = (HttpURLConnection) imageUrl.openConnection(); conn.setConnectTimeout(30000); conn.setReadTimeout(30000); conn.setInstanceFollowRedirects(true); is = conn.getInputStream(); os = new FileOutputStream(f); Utils.CopyStream(is, os); os.close(); bitmap = decodeFile(f); return bitmap; } catch (Exception ex) { Log.e("inNews", "Image Url Malformed"); return null; } } private Bitmap decodeFile(File f) { try { BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; BitmapFactory.decodeStream(new FileInputStream(f), null, o); final int REQUIRED_SIZE = 70; int width_tmp = o.outWidth, height_tmp = o.outHeight; int scale = 1; while (true) { if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE) break; width_tmp /= 2; height_tmp /= 2; scale *= 2; } BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize = scale; return BitmapFactory.decodeStream(new FileInputStream(f), null, o2); } catch (FileNotFoundException e) { } return null; } class PhotosLoader implements Runnable { String url; ImageView imageView; ProgressBar pBar; Bitmap bmp; public PhotosLoader(String url, ImageView imageView, ProgressBar pBar) { this.url = url; this.imageView = imageView; this.pBar = pBar; } @Override public void run() { bmp = getBitmap(url); handler.post(new Runnable() { @Override public void run() { if (bmp != null) { pBar.setVisibility(View.GONE); imageView.setImageBitmap(bmp); } else { pBar.setVisibility(View.GONE); imageView.setImageResource(R.drawable.img_no_image_grid); } } }); } } }
Please help me fix my code. Thanks!
Note: I did not use bitmap.recycle() , as the documentation says that post-Honeycomb GC collects bitmaps, and it no longer needs to be forced to recycle!