I have done some additional investigation and it seems that many
people are having similar symptoms but their fixes aren't working for
me.  One person said they had threads that were not dying but I have
checked that my thread count does not continually increase.

I have been using ExecutorService as set up with
Executors.newSingleThreadExecutor(); to run my server requests.  I
also changed it to just run the handler as a normal thread to see if
that would help out.

I have several other Handlers running as ExecutorService in other
activities as well as some processes running as a normal thread that
uses newBM = BitmapFactory.decodeStream(bis); and those do not produce
the memory leak.

The issue seems to be narrowing down to the map overlays.  Can someone
tell me how to accurately destroy an overlay because it seems like
they are hanging around (though how to detect them I am not sure).

On Jan 10, 8:21 am, jgostylo <jgost...@gmail.com> wrote:
> I have been banging away at this one for weeks and I feel like I have
> exhausted my research capabilities.  I am hoping that someone will see
> my error in the code posted below.  The code is completely functional
> doing everything I need, but there is a major memory leak.
>
> When I try to track memory in the DDMS, the VM Heap tells me that my
> object count is relatively stable and the used memory is also
> relatively stable (it comes back down to a similar value after each GC
> after panning).  When I look at the memory pie chart, the free memory
> loses over 1meg of capacity with each map pan (overlay reload) and the
> Unknown memory grows.  I have not found anything with the allocation
> tracker.
>
> Functional Summary:
> I load overlays onto a map based on data I get from polling my
> server.  When I pan the map far enough I clear the overlays and load
> new ones.
>
> MapFrontEnd.java  (snippets):
> //header info
> private List<Overlay> overlays;
>
> //in onCreate
> overlays = mapView.getOverlays();
> ...
> // here I attempt to fully clean up my old Overlays
> for (Overlay i : overlays)
> {
>      if (i instanceof ParcelOverlay)
>          ((ParcelOverlay) i).cleanUp();}
>
> overlays.clear();
>
> // and now I create the new overlays and add them to the Overlay list
> int count = 0;
> while (count < parcelData.length)
> {
>         try
>         {
>                 overlays.add(new ParcelOverlay(MapFrontEnd.this, parcelData
> [count]));
>         }
> ...
> count++;
>
> }
>
> ParcelOverlay.java (necessary snippets):
>
> public class ParcelOverlay extends Overlay {
>
>         private MapFrontEnd context;
>         private Location location;
>         private GeoPoint locationPoint;
>         private int parcelSize;
>         private int price;
>         private String priceString;
>         private String owner;
>         private int buildingCount;
>         private int haunted;
>         private Bitmap buildingBitmap = null;
>         private Bitmap ghostBitmap = null;
>         private Bitmap presentBitmap = null;
>
>         private boolean selected = false;
>
>         private int backgroundColor;  // ARGB
>         private int gridlineColor;
>         private int selectedColor = 0xBBFAFA14;
>
>         private Typeface face;
>
>         // draw variables
>         private GeoPoint sizePoint;
>         private Paint rectOverlay = new Paint();
>         private Paint rectGrid = new Paint();
>         private Paint textPaint = new Paint();
>         private Paint imagePaint = new Paint();
>         Point topLeft = new Point();
>         Point bottomRight = new Point();
>
>         Point bottomLeft = new Point();
>         Point topRight = new Point();
>
>         public ParcelOverlay(MapFrontEnd _context, ParcelData _parcel) {
>             super();
>             context = _context;
>             locationPoint = new GeoPoint(_parcel.latitude,
> _parcel.longitude);
>             parcelSize = _parcel.size;
>             price = _parcel.cost;
>             owner = _parcel.owner;
>             buildingCount = _parcel.buildingNumber;
>             haunted = _parcel.haunted;
>             prize = _parcel.prize;
>             priceString = Integer.toString(price);
>
>             sizePoint = new GeoPoint(locationPoint.getLatitudeE6() +
> parcelSize, locationPoint.getLongitudeE6() + parcelSize);
>
>             face = Typeface.createFromAsset(context.getAssets(), "fonts/
> sd_led_screen.ttf");
>
>             setupColors();
>
>                 textPaint.setColor(0xd8000000);
>                 textPaint.setTextSize(25);
>                 textPaint.setTypeface(face);
>         }
>
>         @Override
>         public void draw(Canvas canvas, MapView mapView, boolean shadow) {
>                // there are no new objects created in draw
>                 if (shadow == false) {
>                   ...
>                   if (buildingBitmap != null)
>                     canvas.drawBitmap(buildingBitmap, (float)(bottomLeft.x + 
> 5),
> (float)(topRight.y + 5), imagePaint);
>
>                   if (ghostBitmap != null)
>                         canvas.drawBitmap(ghostBitmap, (float)(topRight.x - 
> 30), (float)
> (topRight.y + 3), imagePaint);
>
>                   if (presentBitmap != null)
>                         canvas.drawBitmap(presentBitmap, (float)(topRight.x - 
> 30),
> (float)(bottomLeft.y - 16), imagePaint);
>                   ...
>                 }
>                 super.draw(canvas, mapView, shadow);
>            }
>
>         private void setupColors()
>         {
>             ... //code for setting Paint colors
>
>                 // set the building bitmap
>             if (buildingCount > 5)
>                 buildingBitmap = BitmapFactory.decodeResource
> (context.getResources(), R.drawable.mainstreet);
>             else if (buildingCount > 2)
>                 buildingBitmap = BitmapFactory.decodeResource
> (context.getResources(), R.drawable.tradingpost);
>             else if (buildingCount > 0)
>                 buildingBitmap = BitmapFactory.decodeResource
> (context.getResources(), R.drawable.generalstore);
>             else if (buildingCount == 0)
>             {
>                 if (buildingBitmap != null)
>                 {
>                         buildingBitmap.recycle();
>                         buildingBitmap = null;
>                 }
>             }
>             else
>                 buildingBitmap = BitmapFactory.decodeResource
> (context.getResources(), R.drawable.playerstore);
>
>             if (haunted == 1)
>                 ghostBitmap = 
> BitmapFactory.decodeResource(context.getResources
> (), R.drawable.ghostsmall);
>             else if (ghostBitmap != null)
>             {
>                 ghostBitmap.recycle();
>                 ghostBitmap = null;
>             }
>
>             if (prize == 1)
>                 presentBitmap = 
> BitmapFactory.decodeResource(context.getResources
> (), R.drawable.present);
>             else if (presentBitmap != null)
>             {
>                 presentBitmap.recycle();
>                 presentBitmap = null;
>             }
>         }
>
>         public void cleanUp()
>         {
>                 context = null;
>
>                 if (buildingBitmap != null)
>                 {
>                         buildingBitmap.recycle();
>                         buildingBitmap = null;
>                 }
>                 if (ghostBitmap != null)
>                 {
>                         ghostBitmap.recycle();
>                         ghostBitmap = null;
>                 }
>                 if (presentBitmap != null)
>                 {
>                         presentBitmap.recycle();
>                         presentBitmap = null;
>                 }
>         }
-- 
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Reply via email to