Enhance Performance of mapview with 200+ markers - android

I am having 3 types of overlays on the map.
1) there is one kind of overlays which is having simple markers. And on click of overlay i show pop up.
2) other kind of overlay contains canvas drawing. and onTouch event of these overlays we have to show third kind of overlay which contains bitmap drawing on the map. And click event of third kind of overlay is also there.
so, due to heavy calculations and lots of canvas drawing, performance of mapview is degraded.
I have gone through Overlaymanager libreary from https://github.com/staroud-android/OverlayManager. but its not helping me.
Is there any way which can fulfill my requirements with high performance?
I also need suggestion that Polaris map library can help me for better performance? https://github.com/cyrilmottier/Polaris

What is happening is that you are populating the MapView everytime you add a GeoPoint. Try adding this to your code:
after you have looped through the GeoPoints place this code
itemizedOverlay.populateNow();
and change you itemizedOverlay to look like this:
public void addOverlay(OverlayItem overlay) {
m_overlays.add(overlay);
}
public void populateNow()
{
populate();
}
#Override
protected OverlayItem createItem(int i) {
return m_overlays.get(i);
}
#Override
public int size() {
return m_overlays.size();
}

Related

Load Map with bubbles on page load in android

In my application there is a map and the map has many pins. When the user taps on a pin, name of the touched pin appears in a balloon. What I want is to display all balloons on page loads, not when the user touches a pin. I have written the ItemizedOverlayWithBubble class and it overrides a method called onSingleTapUpHelper:
#Override protected boolean onSingleTapUpHelper(final int index, final Item item, final MapView mapView) {
showBubbleOnItem(index, mapView, true);
return true;
}
Inside that there is another method call showBubbleOnItem(index, mapView, true);
public void showBubbleOnItem(final int index, final MapView mapView, boolean panIntoView) {
ExtendedOverlayItem eItem = (ExtendedOverlayItem)(getItem(index));
mItemWithBubble = eItem;
if (eItem != null){
eItem.showBubble(mBubble, mapView, panIntoView);
//setFocus((Item)eItem);
}
}
I played around with it for a while to see if I could get it working on page load but got no luck. Any help is greatly appreciated.
Possibly your points are overlaps with each other. Especially if you create GeoPoints from integers with small difference like 11,1 and 12,2 and 13,3 this will couse overlaped overlay items
Have a look at here
package org.osmdroid.util.GeoPoint
when you use
GeoPoint(final int aLatitudeE6, final int aLongitudeE6)
Your value will not be multiplyed with 1E6(which is 1.000.000)
So there is no place difference between this two points on MapView
GeoPoints(11,1) and GeoPoints(12,2)

Is it possible to batch adding polygons to GoogleMap View (APIv2)

I'm drawing a bunch (50-500) polygons on a Google MapView (API v2) in Android 4.0+, and trying to modify them with a touch event. The touch event I trap via dispatchTouchEvent(), and it's working, just very slowly. The performance is bad enough that it doesn't 'feel' like it's working.
I believe the problem lies in the fact that I have to loop through a collection of polygons, adding them to the map one at a time, so the map redraws with each one.
Looking through the documentation I cant see a way to add multiple polygons at once, but maybe I'm missing something. Any help would be appreciated.
My dispatchTouchEvent looks something like this:
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if(mInDrag||mInRotate||mInAB){
if (ev.getAction()==MotionEvent.ACTION_DOWN){
mStartPt = mMap.getProjection().fromScreenLocation(new Point((int)ev.getX(), (int)ev.getY()));
mLastDragTime=System.currentTimeMillis();
} else if (ev.getAction()==MotionEvent.ACTION_MOVE){
LatLng endPt = mMap.getProjection().fromScreenLocation(new Point((int)ev.getX(), (int)ev.getY()));
long iterationTime = System.currentTimeMillis()-mLastDragTime;
//checking iterationtime so grid doesn't move after the user stops dragging
if ((!mStartPt.equals(endPt))&&iterationTime<300) {
LatLng delta = new LatLng(mStartPt.latitude-endPt.latitude, mStartPt.longitude-endPt.longitude);
mLastDragTime=System.currentTimeMillis();
if (mInDrag) {
//setup calcs
} else if (mInAB){
//setup calcs
} else if (mInRotate){
//setup calcs
}
clearTempGrid(); //clears the grid including erasing the existing polygons on the map.
int gridType = gridTypeSpin.getSelectedItemPosition();
for (PolygonOptions newPolygon : myPolygonGrid.modify(A, B)) {
//I run into problems here. Even 150 polygons slows it down
Polygon myPolygon = mMap.addPolygon(newPolygon);
tempPolygons.add(myPolygon);
}
}
}
}
return super.dispatchTouchEvent(ev);
}
Are you sure what you want is to modify all Polygons when dragging?
Add Polygons once and not clear and recreate them every time you get touch event.
Modify them (all?) with Polygon.setPoints(...).

MapView very slow with 1000 overlayitems on the map, even with only 2 visibles

I have a mapview showing 1000 overlayitems on the mapview. The map moves very slow even if only two overlayitems are visibles on the map (huge zoom applyed)
It is possible to optimice the mapview to move more fast if only low cuantity of overlayitems are visibles?
Thanks
You might have fallen in the usual pit. If you've made your own customoverlay make sure that your addOverlay methode don't populate. Populate should first happen when all overlays has been added. If you populate each time you add you'll end up with many overlays on top of each other.
Make sure it uses 2 methods for this process, 1 to add and 1 to populate:
public void addOverlay(CustomOverlayItem overlay) {
mOverlays.add(overlay);
}
public void populateOverlay() {
populate();
}
If that is not the issue then you should look into dynamically removing pins when they are outside the screen range or grouping pins together. I believe there is some open source project that have done the work for you in this regard.
Found a link http://onthefencedevelopment.com/blog/using-google-maps-your-android-applications-%E2%80%93-part-3-adding-place-markers drawing only the overlays which are on the screen. haven't tested it yet but seems promising.
EDIT: it works
subclass MapView, override dispatchDraw(). Detect changes in map center or zoom level:
#Override
public void dispatchDraw(Canvas canvas)
{
super.dispatchDraw(canvas);
GeoPoint gpCenterPoint = getMapCenter();
int nZoomLevel = getZoomLevel();
// either diff't zoom level or change to center point?
if ( (gpCenterPoint.getLatitudeE6() != mCenterPoint.getLatitudeE6()) ||
(gpCenterPoint.getLongitudeE6() != mCenterPoint.getLongitudeE6()) ||
(nZoomLevel != mZoomLevel) )
{
// update pins here
updatePINS();
mZoomLevel = nZoomLevel;
mCenterPoint = gpCenterPoint;
}
}
void updatePINS()
{
int nLatitudeSpan = mapView.getLatitudeSpan();
int nLongitudeSpan = mapView.getLatitudeSpan();
// TODO insert/remove PINS as needed
}

ItemizedOverlay and custom marker on OsmDroid for Android, no more touch event

I'm curently using a class which extends from the Drawable on OsmDroid.
And on this class I draw a geometric form for each car I receive from internet.
I would like to add a listener on each car in order to give some informations when we touch the car.
With a OverlayItem we can do this :
ArrayList<OverlayItem> items = new ArrayList<OverlayItem>();
carOverlay.draw(new Canvas());
overlayItem = new OverlayItem("test", ""+i, geoPoint);
overlayItem.setMarker(carOverlay.getCurrent());
items.add(overlayItem);
ItemizedOverlay<OverlayItem> overlay = new ItemizedOverlayWithFocus<OverlayItem>(this.getApplicationContext(), items,
new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() {
#Override
public boolean onItemSingleTapUp(final int index, final OverlayItem item) {
Log.i("Touch","you just tap the car");
return true;
}
#Override
public boolean onItemLongPress(final int index, final OverlayItem item) {
return false;
}
});
With this piece of code, I can see the image I've just drawn, but no event when I touch a car, and if I remove the line :
overlayItem.setMarker(carOverlay.getCurrent());
to let the default marker being displayed instead of my custom marker, the touch events occure.
So what am I doing wrong ? must be the same no ?
This is not a 'proper' answer but as I am facing similar problem I resorted to using BOTH default draw and custom at the same time.
I just call super() at the end of my custom draw method on ItemizedIconOverlay and both my drawing and 'default' item marker are drawn.
Maybe it would be possible to tweak default marker to make it invisible (empty bitmap)... experiment. :)
#Override
public void draw(Canvas canvas, MapView mv, boolean shadow) {
if(!shadow) {
//my draw code
}
super.draw(canvas, mv, shadow);
}
tmouse is correct. If you're overriding the ItemizedOverlayWithFocus.draw() method to draw your car with canvas, you'll need to add:
super.draw(canvas, view, shadow);
The super will setup and use the OverlayItem's Hotspot which is (from what I can see in the source) used as the touchable area for gestures.
However you'll still see the original Markers AND your canvas drawn ones. PLUS if you move your cars, the touchable area won't move with it. (the Hotspot will not be for the new location you drew at)
There are only 2 real solutions.
1) You re-implement ItemizedOverlayWithFocus.draw() and ItemizedOverlayWithFocus.onDrawItem() in your own ItemizedOverlayWithFocus class. (only you'll call onDrawItem(), onDrawCar(), and call it instead from the overridden draw() method)
That's not worth it unless you want to change the offset of the Marker being drawn. e.g. I have a tower icon, and I want 10 pixels from the bottom to be the Y point so it looks like the tower is standing on the GeoPoint, not at the edge of it.
2) You create your own Markers from a Bitmap first, and set it as a Drawable Marker in the OverlayItem.setMarker() method. Try creating a a Bitmap using Canvas:
Bitmap bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
// Draw on your car on the canvas...
Then try assigning the Bitmap:
overlayItem.setMarker(new BitmapDrawable(bitmap));
Don't override draw() unless you want to draw some other stuff, and if you do ensure you super.draw() so the Marker and its Hotspot work with the gestures.
You can try also this code
Drawable newMarker = this.getResources().getDrawable(R.drawable.ic_marker);
this.mMyLocationOverlay = new ItemizedIconOverlay<OverlayItem>(items,
newMarker, "listener try null", new DefaultResourceProxyImpl(getActivity()));
mapView.getOverlays().add(mMyLocationOverlay);

Remove overlay in the map

My application search and visual same overlays. But, in the next search the old overlay are not clear. I have to try to use map.getOverlays().clear(); but it remove also the overlay of MyLocationOverlay. There is a method for delete only same overlay?
I know its a little too late, but since i came up with a solution that helped me, i thought of sharing it so that it helps programmers in the future..
#hooked82 : the problem with doing just
overlays.remove(position)
is that its a list. so when you remove one item from the list, every item to the right of this item, in the list, is shifted one place to the left, which will eventually mess up your positions making it really tedious to keep a track of them all over time.
During one of my projects, i faced the same issue. Since i was adding and removing overlays upon some updates, after a point of time, it was really difficult to keep a track of the overlay positions in the list.
Here is what i did as a work around for the problem, and so far there have been no issues.
Step 1: create your custom Overlay Class
public class MyOverlay extends Overlay
{
private String overlayUUID;
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow)
{
-- do what you need to do here --
}
public String getOverlayUUID()
{
return overlayUUID
}
}
Step 2: in the MapClass where you handle the overlays. Please be sure that the mapOverlays list is a global list in the MapView class where you add all your mapOverlays
List<Overlay> mapOverlays = mapView.getOverlays();
public void removeChosenOverlay(String overlayUUID)
{
for(int i=0; i<mapOverlays.size(); i++)
{
String className = mapOverlays.get(i).getClass().getSimpleName();
if(className.equals("MyOverlay"))
{
MyOverlay myOverlay = (MyOverlay) mapOverlays.get(i);
if((myOverlay != null) && (myOverlay.getOverlayUUID.equals(overlayUUID)))
{
mapOverlays.remove(i);
mapView.invalidate()
break;
}
}
}
}
With the above method, one can uniquely identify each overlay with a UUID (in my case it was a string, but you can custom create your UUID's in any format you wish to) and remove the corresponding overlay item successfully from the list of overlays, without having to worry about their relative positions in the list.
I hope it helps others who face the same issues with uniquely identifying overlays.
When you add overlays to your map, you can add it to a certain position
overlays.add(position, overlay_object);
Then when you need to remove specific overlays, you can remove them in the same fashion
overlays.remove(position);
you can do this with the help of the counter and another reference to the overlayItem to save old overlay which you want to remove
in my case counter is current_overlay_counter and old_overlay_item get the reference for old overlay
on the first call the counter is 0 so there is no overlay to remove
public void getcurrentPostion()
{
GeoPoint gpoint=new GeoPoint((int)((current_location.getLatitude())*1E6),( (int)((current_location.getLongitude())*1E6)));
OverlayItem overlayitem = new OverlayItem(gpoint, "Hola, Mundo!", "I'm in Mexico City!");
mapOverlays = map.getOverlays();
itemizedoverlay.addOverlay(overlayitem);
mapOverlays.add(itemizedoverlay);
if(current_overlay_counter>0)
{
System.out.println("deleting overlay");
itemizedoverlay.removeOverlay(old_overlay_item);
map.invalidate();
}
old_overlay_item=overlayitem;
current_overlay_counter++;
map_controller.setCenter(gpoint);
}
you need one more thing ,a method to remove the overlay in your ItemizedOverlay class implementation
this method takes the referece of the overlay you want to delete
public void removeOverlay(OverlayItem overlay){
mOverlays.remove(overlay);
System.out.println("removeOverlay is called");
populate();
}

Categories

Resources