位置每35秒更新一次,并在当前位置绘制一个圆圈

目前,我每隔35秒改变位置并移动10米距离,就在我的Current Location绘制一个Circle

因此,一旦位置发生变化(移动35秒和10米),我就在LocationChanged下实现了此function,我Circle on the Google Maps on the Current Location绘制了一个Circle on the Google Maps on the Current Location

问题陈述:-

My App is running very slow 。 有时我的应用程序被绞死了? 可能是因为我的代码不像我在下面写的那样有效吗?

基本上,我只需要在每35秒移动10米的距离后在当前位置画一个圆圈。

我的代码有问题吗? 任何想法,比如我应该如何改进这一点,顺利运行它。

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); locationListener = new GPSLocationListener(); locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 35000, 10, locationListener); mapView = (MapView) findViewById(R.id.mapView); listView = (ListView) findViewById(R.id.mylist); mapView.setStreetView(true); mapView.setBuiltInZoomControls(true); mapController = mapView.getController(); mapController.setZoom(15); } private class GPSLocationListener implements LocationListener { @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); // add marker MapOverlay mapOverlay = new MapOverlay(this,android.R.drawable.star_on); mapOverlay.setPointToDraw(point); List listOfOverlays = mapView.getOverlays(); listOfOverlays.clear(); listOfOverlays.add(mapOverlay); String address = ConvertPointToLocation(point); Toast.makeText(getBaseContext(), address, Toast.LENGTH_SHORT).show(); mapView.invalidate(); } } @Override public void onProviderDisabled(String provider) { } @Override public void onProviderEnabled(String provider) { } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } } 

这是我的MapOverlay类,我正在绘制一个Circle。

 class MapOverlay extends Overlay { private GeoPoint pointToDraw; int[] imageNames=new int[6]; public MapOverlay(GPSLocationListener gpsLocationListener, int currentUser) { imageNames[0]=currentUser; } public void setPointToDraw(GeoPoint point) { pointToDraw = point; } public GeoPoint getPointToDraw() { return pointToDraw; } @Override public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) { super.draw(canvas, mapView, shadow); //---translate the GeoPoint to screen pixels--- Point screenPts = new Point(); mapView.getProjection().toPixels(pointToDraw, screenPts); //--------------draw circle---------------------- Point pt = mapView.getProjection().toPixels(pointToDraw,screenPts); Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); circlePaint.setColor(0x30000000); circlePaint.setStyle(Style.FILL_AND_STROKE); int totalCircle=4; int radius=40; int centerimagesize=35; for (int i = 1; i <= totalCircle; i ++) { canvas.drawCircle(screenPts.x,screenPts.y, i*radius, circlePaint); } canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),imageNames[0]), (screenPts.x-(centerimagesize/2)),(screenPts.y-(centerimagesize/2)), null); super.draw(canvas,mapView,shadow); return true; } } 

更新的代码: –

 private MapView mapView; private ListView listView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mapView = (MapView) findViewById(R.id.mapView); listView = (ListView) findViewById(R.id.mylist); locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); locationListener = new GPSLocationListener(mapView); locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 35000, 0, locationListener); mapView.setStreetView(true); mapView.setBuiltInZoomControls(true); mapController = mapView.getController(); mapController.setZoom(15); } private class GPSLocationListener implements LocationListener { MapOverlay mapOverlay; public GPSLocationListener(MapView mapView) { mapOverlay = new MapOverlay(this,android.R.drawable.star_on); List listOfOverlays = mapView.getOverlays(); listOfOverlays.add(mapOverlay); } @Override public void onLocationChanged(Location location) { if (location != null) { GeoPoint point = new GeoPoint( (int) (location.getLatitude() * 1E6), (int) (location.getLongitude() * 1E6)); mapController.animateTo(point); mapController.setZoom(15); // **See no need to make a new Object here** mapOverlay.setPointToDraw(point); mapView.invalidate(); } } @Override public void onProviderDisabled(String provider) { } @Override public void onProviderEnabled(String provider) { } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } } class MapOverlay extends Overlay { private GeoPoint pointToDraw; int[] imageNames=new int[6]; private Point mScreenPoints; private Bitmap mBitmap; private Paint mCirclePaint; public MapOverlay(GPSLocationListener gpsLocationListener, int currentUser) { imageNames[0]=currentUser; mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mCirclePaint.setColor(0x30000000); mCirclePaint.setStyle(Style.FILL_AND_STROKE); mBitmap = BitmapFactory.decodeResource(getResources(),imageNames[0]); 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); mScreenPoints = mapView.getProjection().toPixels(pointToDraw, mScreenPoints); int totalCircle=4; int radius=40; int centerimagesize=35; for (int i = 1; i <= totalCircle; i ++) { canvas.drawCircle(mScreenPoints.x,mScreenPoints.y, i*radius, mCirclePaint); } canvas.drawBitmap(mBitmap, (mScreenPoints.x-(centerimagesize/2)),(mScreenPoints.y-(centerimagesize/2)), null); super.draw(canvas,mapView,shadow); return true; } } 

绘图时要记住以下几点:

  1. 不要阻止主UI线程
  2. 记住回收对象。
  3. 记住回收对象。
  4. 并始终记住回收对象。

可能的UI线程阻塞

这段代码看起来在onLocationChanged()的回调上调用了一个可能很昂贵的操作,这样做真的很危险,因为你可能最终会遇到ANR。 这可能应该在后台AsyncTask上完成,然后在结果上显示toast。

 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 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 decoded 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.decodeResource(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; }