Search code examples
androidosmdroid

Launch intent on click on a MarkerInfoWindow with osmbonuspack


I have a GridMarkerClusterer with some Marker in it representing shared bike stations. I want those markers have a custom MarkerInfoWindow (bubble) with a click listener so that when the user clicks on the bubble, a new intent is launched.

Thus far, I'm OK.

Now I want to put extra data (station information corresponding to the marker) to that intent.

What I actually did is to add a constructor in my StationMarkerInfoWindow which takes a Station in parameter. I then add this parameter to the intent with putExtra() in my OnClickListener.

That's working but what is wrong is that I need to create a new StationMarkerInfoWindow for each marker instead of using the same object, and if I have more than 1000 markers to display, the activity takes up to 10 seconds to be created on my device (~1 second if I use the same StationMarkerInfoWindow object for each marker).

The question is: how should I add those data to the intent?

Here are the relevant parts of the code:


public class MapActivity extends Activity {

    private BikeNetwork bikeNetwork;
    private ArrayList<Station> stations;
    private MapView map;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_map);

        // ...

        stations = bikeNetwork.getStations();

        map = (MapView) findViewById(R.id.mapView);

        GridMarkerClusterer stationsMarkers = new GridMarkerClusterer(this);
        Drawable clusterIconD = getResources().getDrawable(R.drawable.marker_cluster);
        Bitmap clusterIcon = ((BitmapDrawable) clusterIconD).getBitmap();
        map.getOverlays().add(stationsMarkers);
        stationsMarkers.setIcon(clusterIcon);
        stationsMarkers.setGridSize(100);

        for (final Station station : stations) {
            stationsMarkers.add(createStationMarker(station));
        }

        // ...
    }

    private Marker createStationMarker(Station station) {
        Marker marker = new Marker(map);
        marker.setInfoWindow(new StationMarkerInfoWindow(
                R.layout.bonuspack_bubble, map, station)); // this seems wrong
        marker.setInfoWindow(stationMarkerInfoWindow);
        marker.setPosition(stationLocation);
        marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER);
        marker.setIcon(getResources().getDrawable(R.drawable.ic_bike));
        marker.setTitle(station.getName());
        marker.setSnippet(String.valueOf(station.getFreeBikes())); // free bikes
        marker.setSubDescription(String.valueOf(station.getEmptySlots())); // empty slots

        return marker;
    }

    private class StationMarkerInfoWindow extends MarkerInfoWindow {
        Station station;

        public StationMarkerInfoWindow(int layoutResId, final MapView mapView, final Station station) {
            super(layoutResId, mapView);
            this.station = station;
        }

        @Override
        public void onOpen(Object item) {
            super.onOpen(item);
            closeAllInfoWindowsOn(map);

            LinearLayout layout = (LinearLayout) getView().findViewById(R.id.map_bubble_layout);
            layout.setClickable(true);
            layout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent intent = new Intent(MapActivity.this, StationActivity.class);
                    intent.putExtra("station", station);
                    startActivity(intent);
                }
            });
        }
    }
}

Solution

  • I would suggest to set the Station as the "related object" of its Marker:

    marker.setRelatedObject(station);
    

    You can then retrieve this related object in StationMarkerInfoWindow#onOpen:

    Marker marker = (Marker)item;
    selectedStation = (Station)marker.getRelatedObject();
    

    Similar implementation can be found here.

    Then you can share the same StationMarkerInfoWindow.