Местоположение обновляется каждые 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 ответ:
Вот несколько вещей, которые следует помнить при рисовании:
- не блокируйте основной поток пользовательского интерфейса
- запомните объекты рециркуляции.
- запомните объекты рециркуляции.
- и всегда помните, что нужно перерабатывать объекты.
Возможная блокировка потока пользовательского интерфейса
Этот код выглядит так, как будто он вызывает потенциально дорогостоящее действие по обратному вызову
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; }