I am working with a custom MapView for an application. I have a database with a LOT of GPS datapoints saved and I am currently loading them using Overlays, then performing an .addAll on the MapView with the Overlays.
However, it is taking up to 2 minutes to load just a few hundred data points as a path on the MapView.
The code to load the Data Points is:
private void loadMap() {
//Load the specific data from the database
DBAdapter db = new DBAdapter(this);
try {
db.open();
Cursor mDataPoints = db.db.rawQuery("SELECT * FROM GPS_DATA)", null);
if ((mDataPoints != null) && (!mDataPoints.isClosed()) && (mDataPoints.moveToFirst())) {
mapMain.setFinishedLoading(false);
mapMain.getOverlays().clear();
if ((!mDataPoints.isClosed()) && (mDataPoints.moveToFirst())) {
while (!mDataPoints.isAfterLast()) {
this.drawPath(db,
DBAdapter.formatLong(mDataPoints, "data_id"),
DBAdapter.formatString(mDataPoints, "data_name"),
DBAdapter.formatString(mDataPoints, "data_type"));
mDataPoints.moveToNext();
}
}
mapMain.refreshDrawableState();
mapMain.setEnabled(true);
}
} finally {
db.close();
}
}
public void drawPath(DBAdapter db, long pDataID, String pDataName, String pDataType) {
Cursor mData = db.getPointDataByDataID(pDataID);
if ((!mData.isClosed()) && (mData.moveToFirst())) {
boolean vFirst = true;
int i = 0;
GeoPoint startGP;
GeoPoint geoPoint1;
GeoPoint geoPoint2 = null;
while (!mData.isAfterLast()) {
if (vFirst) {
startGP = new GeoPoint((int) (DBAdapter.formatDouble(mData, "latitude") * 1E6), (int) (DBAdapter.formatDouble(mData, "longitude") * 1E6));
mapMain.getOverlays().add(new Map_Route_Overlay(startGP, startGP, this.returnPathColor(pDataType), pDataName));
vFirst = false;
geoPoint2 = startGP;
} else {
geoPoint1 = geoPoint2;
geoPoint2 = new GeoPoint((int) (DBAdapter.formatDouble(mData, "latitude") * 1E6), (int) (DBAdapter.formatDouble(mData, "longitude") * 1E6));
if (geoPoint2.getLatitudeE6() != 22200000) {
mapMain.getOverlays().add(new Map_Route_Overlay(geoPoint1, geoPoint2, this.returnPathColor(pDataType), pDataName));
}
}
i += 1;
mData.moveToNext();
}
if (geoPoint2 != null) {
mapMain.getOverlays().add(new Map_Route_Overlay(geoPoint2, geoPoint2, this.returnDataColor(pDataType), pDataName));
}
}
mData.close();
}
public int returnDataColor(String pType) {
int vReturnData = Color.BLUE;
if (pType.trim().equals("S")) {
vReturnData = Color.RED;
}
return vReturnData;
}
And the code for the Map_Route_Overlay class is:
public final class Map_Route_Overlay extends Overlay {
private static String TAG = CoreFunctions.APP_TAG + "_MapRouteOverlay";
private GeoPoint geoPoint1;
private GeoPoint geoPoint2;
private int defaultColor = 999;
private String dataName = "";
public Map_Route_Overlay(GeoPoint pGeoPoint1, GeoPoint pGeoPoint2, int pColor, String pText) {
this.geoPoint1 = pGeoPoint1;
this.geoPoint2 = pGeoPoint2;
this.defaultColor = pColor;
this.dataName = pText;
}
public void setDataName(String pName) {
this.dataName = pName;
}
@Override
public boolean draw (Canvas canvas, MMMapView mapView, boolean shadow, long when) {
Projection projection = mapView.getProjection();
if (shadow == false) {
Paint paint = new Paint();
paint.setAntiAlias(true);
Point point = new Point();
projection.toPixels(this.geoPoint1, point);
paint.setColor(this.defaultColor);
Point point2 = new Point();
projection.toPixels(this.geoPoint2, point2);
paint.setStrokeWidth(2);
paint.setAlpha(this.defaultColor == Color.parseColor("#6C8715")?220:120);
canvas.drawLine(point.x, point.y, point2.x,point2.y, paint);
}
return super.draw(canvas, mapView, shadow, when);
}
}
I have tried several options, including loading the data using Threads, but notifying the MapView to load the Overlays when completed was becoming a nightmare.
Just for reference, MMMapView is my custom MapView component, which for now just inherits MapView and implements two functions.
You really shouldn't be trying to display hundreds of Overlays on the screen at once, because you will get bad performance. Try limiting it to 10-20. Any more than that and it is too busy for the user anyway.
Also you should be using a thread to load the items from your database. What I do is I use a custom ItemizedOverlay, and add custom OverlayItems to it in a thread. Then once I am done loading I call mapView.postInvalidate();
so that they are displayed on the screen.