绘制时需要记住以下几点:
- 不要阻塞主UI线程
- 记住回收对象。
- 记住回收对象。
- 并始终记住回收对象。
可能的UI线程阻塞
这段代码看起来像在回调上调用一个潜在的昂贵动作
onLocationChanged(),这样做真的很危险,因为您可能会遇到ANR。这可能应该在后台AsyncTask上完成,然后在其结果上显示吐司。
String address = ConvertPointToLocation(point);Toast.makeText(getbaseContext(), address, Toast.LENGTH_SHORT).show();
更好地管理地图资源
确保每次都回收实例并重置其位置,而不是每次都添加新的叠加层。
private class GPSLocationListener implements LocationListener { MapOverlay mOverlay; public GPSLocationListener() { } @Override public void onLocationChanged(Location location) { if (location != null) { GeoPoint point = new GeoPoint( (int) (location.getLatitude() * 1E6), (int) (location.getLongitude() * 1E6)); findUsersInCurrentRadius(4,location.getLatitude(),location.getLongitude()); mapController.animateTo(point); mapController.setZoom(15); if (mOverlay == null) { // Add this marker to the list of overlays always. // This stuff never changes so there is no need to do this logic // Every 30 secs. Loading images is **Expensive** mOverlay = mMapOverlay = new MapOverlay(this,android.R.drawable.star_on); List<Overlay> listOfOverlays = mapView.getOverlays(); listOfOverlays.add(mMapOverlay); } // **See, no need to make a new Object here** mOverlay.setPointToDraw(point); // This can probably be done at another time. // String address = ConvertPointToLocation(point); // Toast.makeText(getbaseContext(), address, Toast.LENGTH_SHORT).show(); mapView.invalidate(); }这段代码可以重用此标记,并且只需更新其位置即可。如果不在列表中,则只应创建一个。
更好的绘图
好的,接下来请记住,如果不需要,不要在onDraw()方法中创建对象。一旦标记知道要绘制到的位置,就应该缓存所有内容,以便您可以专注于绘制。例如:
public class MapOverlay { private GeoPoint pointToDraw; int[] imageNames=new int[6]; // This is the cached Point on the screen that will get refilled on every draw private Point mScreenPoints; // This is the cached depred bitmap that will be drawn each time private Bitmap mBitmap; // Cached Paint private Paint mCirclePaint; public MapOverlay(GPSLocationListener gpsLocationListener, int currentUser) { imageNames[0]=currentUser; // This only needs to be made here, once. It never needs to change. mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mCirclePaint.setColor(0x30000000); mCirclePaint.setStyle(Style.FILL_AND_STROKE); // We only need to load this image once and then just keep drawing it when dirtyed. mBitmap = BitmapFactory.depreResource(context.getResources(),imageNames[0]); // This Point object will be changed every call to toPixels(), but the instance can be recycled mScreenPoints = new Point(); } public void setPointToDraw(GeoPoint point) { pointToDraw = point; } public GeoPoint getPointToDraw() { return pointToDraw; } public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) { super.draw(canvas, mapView, shadow); // In the case where nothing has been set yet, don't do any drawing if (pointToDraw == null) { return true; } //--------------draw circle---------------------- mScreenPoints = mapView.getProjection().toPixels(pointToDraw, mScreenPoints); int totalCircle=4; int radius=40; int centerimagesize=35; for (int i = 1; i <= totalCircle; i ++) {canvas.drawCircle(screenPts.x,screenPts.y, i*radius, mCirclePaint); } canvas.drawBitmap(mBitmap, (screenPts.x-(centerimagesize/2)),(screenPts.y-(centerimagesize/2)), null); super.draw(canvas,mapView,shadow); return true; }


