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

时间:2012-09-16 23:58:49

标签: java android location

目前,我每隔35秒更换一次Circle Current Location并移动10米距离。

所以,一旦位置发生变化(35秒移动10米),我就在LocationChanged下实现了此功能,我正在绘制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<Overlay> 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类。

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<Overlay> 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 个答案:

答案 0 :(得分:1)

绘图时要记住以下几点:

  1. 不要阻止主UI线程
  2. 记住回收对象。
  3. 记住回收对象。
  4. 并且始终记得回收对象。
  5. 可能的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<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 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;
        }