Местоположение обновляется каждые 35 секунд и нарисуйте круг на текущем местоположении


В настоящее время я рисую Circle на моем Current Location после каждых 35 секунд изменения местоположения и перемещения на 10 метров расстояния.

Таким образом, я реализовал эту функцию в разделе LocationChanged, как только местоположение изменяется(35 секунд и 10 метров перемещены), я рисую 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 2

1 ответ:

Вот несколько вещей, которые следует помнить при рисовании:

  1. не блокируйте основной поток пользовательского интерфейса
  2. запомните объекты рециркуляции.
  3. запомните объекты рециркуляции.
  4. и всегда помните, что нужно перерабатывать объекты.

Возможная блокировка потока пользовательского интерфейса

Этот код выглядит так, как будто он вызывает потенциально дорогостоящее действие по обратному вызову 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();
    }

Этот код может повторно использовать этот маркер и просто обновить его позицию. Вы должны создать только один, если его нет в списке.

Лучший Рисунок

Ok далее помните, что не создавайте объекты в методе 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;
    }