Search code examples
androidgoogle-mapspositionrefreshmarkers

Refresh many Google Map markers position, without refresh the whole map in Android


I'm currently developing an Android app that have to receive GPS positions from other devices every minutes, and display them on a map. I'm using the GoogleMaps Api V2,

What i'd like to do, is to refresh the position marker very time a new position is received. (I don't want to refresh the whole map)

For the moment, I've added a button in the menu that enables me to refresh the entire map.

To detail to structure, I have a service that run MQTT, and every time a position is received, I add it into an Hashmap, that represents my map data source. This HashMap is a Singleton that extends Observable. Moreover, my fragment that display the my implements Observer.

Code from my Fragment that implements Observer

 public void update(Observable observable, final Object object)
 {

     if (observable instanceof ListPositions && object != null)
     {        
         Position p = (Position) object;
         LatLng position = new LatLng(p.getLatitude(), p.getLongitude());
         // Where i'd like to move the markers

     }
     else
     {
        // Where i'd like to remove the marker from the map
     }
 }

Code From my Singleton List of position

public class ListPositions extends Observable{

private HashMap<String,Position> mapPosition;

private ListPositions()
{
    mapPosition = new HashMap<String, Position>();
    VehicleMapFragment mapFragmentObserver = new VehicleMapFragment();
    this.addObserver(mapFragmentObserver);
}


private static ListPositions INSTANCE = null;


public static synchronized ListPositions getInstance()
{
    if (INSTANCE == null)
    { INSTANCE = new ListPositions();
    }
    return INSTANCE;
}

public int getNumberOfPosition()
{
    return mapPosition.size();
}

public void addPosition(String key, Position p){
    mapPosition.put(key,p);
    setChanged();
    notifyObservers(p);
}

public void removePosition(String key){
    mapPosition.remove(key);
    setChanged();
    notifyObservers();
}

Code From myService that runs MQTT

public void onPositionMessageReceived(MqttMessage message, String source)
 {
    Gson gson = new Gson();
    String s = gson.toJson(message.toString());
    String jsonPosition = gson.toJson(message.toString());
    jsonPosition = formatMessage(jsonPosition);
    Position p = gson.fromJson(jsonPosition, Position.class);

    ListPositions.getInstance().addPosition(source, p);


}

Can someone know how to move each markers individually without refreshing the whole map, in my update function from my Observer Fragment? May I use a Handler to update the Map, from an other thread to modify the Main UI Thread ?

Many thanks

EDIT :

Because the first methode given by AniV didn't work for me, I've tried with an Asyntask that runs when my Observer get a notification from the Observable List.

Code from the Observer Fragment :

public void update(Observable observable, final Object object)
{
    if (observable instanceof ListPositions && object != null)
    {
        Position p = (Position) object;

        position = new LatLng(p.getLatitude(), p.getLongitude());
        options = new MarkerOptions().position(position).title("TEST").snippet("TEST");

        PositionUpdate positionUpdaterTask = new PositionUpdate(myGoogleMap, options, position);
    positionUpdaterTask.execute();
    }
}

Code from the AsyncTask :

public class PositionUpdate extends AsyncTask<Void, Void, Void>{

private GoogleMap myGoogleMap;
private MarkerOptions options;
private LatLng positionToAdd;


public PositionUpdate(GoogleMap googleMap, MarkerOptions options, LatLng position)
{
    this.myGoogleMap = googleMap;
    this.options = options;
    this.positionToAdd = position;
}


@Override
protected Void doInBackground(Void...voids)
{
    return null;
}

@Override
protected void onPostExecute(Void aVoid)
{
    if (myGoogleMap != null)
    {
        myGoogleMap.addMarker(options.position(positionToAdd));
        Log.i(ConstElisa.LOG_ELISA, "MARKER ADDED");
    }
    else
    {
        Log.e(ConstElisa.LOG_ELISA, "ERROR ADDING THE MARKER");
    }

    super.onPostExecute(aVoid);
}

However, in this case, myGoogleMap variable is always null, so the marker is never added to the Google Map.

Does someone have an idea why this variable is null ?


Solution

  • I finally succeeded in doing that thing by using the AsyncTask.

    In my EDIT, I said that I had some trouble with the null instance of my Google Maps object. This was caused by my Singleton Observable. Indeed, in the constructor, I used

    VehicleMapFragment mapFragmentObserver = new VehicleMapFragment();
    this.addObserver(mapFragmentObserver); 
    

    This code sample recreated another instance of my Fragment, and that the reason why ii had Null objects.

    To correct this problem, I simply used :

    ListPositions.getInstance().addObserver(this);
    

    in my Fragment Observer.

    So if you want to update a marker position without refreshing the whole map, you can use the Observer/Observable Pattern, and use an Asynctask to update the marker position.