在Android中刷新许多Google地图标记的位置,而不必刷新整个地图

3
我正在开发一款安卓应用程序,需要每分钟从其他设备接收GPS位置,并在地图上显示它们。 我正在使用GoogleMaps API V2。
我想做的是,每当接收到新的位置时就刷新位置标记。(我不想刷新整个地图)
目前,我在菜单中添加了一个按钮,可以使我刷新整个地图。
具体结构如下:我有一个运行MQTT的服务,每次接收到位置后,我将其添加到HashMap中,这个HashMap表示我的地图数据源。这个HashMap是一个扩展Observable的Singleton。此外,我的Fragment会实现Observer。
以下是我的Fragment代码(实现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
     }
 }

从我的单例位置列表中获取代码

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();
}

来自我的服务的运行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);


}

您好,以下是您需要翻译的内容:

在我的Observer Fragment的更新函数中,有没有人知道如何单独移动每个标记,而无需刷新整个地图?可以使用Handler从另一个线程更新地图来修改主UI线程吗?

非常感谢

编辑:

因为AniV给出的第一种方法对我不起作用,所以我尝试使用Asyntask,在观察者收到可观察列表的通知时运行。

观察者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();
    }
}

来自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);
}

然而,在这种情况下,myGoogleMap变量始终为空,因此标记永远不会添加到Google地图上。
有人知道为什么这个变量为空吗?
3个回答

1

我最终通过使用AsyncTask成功完成了那件事。

在我的修改中,我提到了我在处理Google Maps对象的null实例时遇到了一些问题。这是由我的单例Observable引起的。事实上,在构造函数中,我使用了

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

这段代码样例重新创建了我的一个Fragment实例,这就是为什么它有空对象的原因。
为了解决这个问题,我只需要使用以下代码:
ListPositions.getInstance().addObserver(this);

在我的Fragment观察者中。

因此,如果您想在不刷新整个地图的情况下更新标记位置, 您可以使用观察者/可观察模式,并使用异步任务来更新标记位置。


干得好...对我的参考也很有帮助 :) - AniV

0

你在这里有两个选项:

  • 要么使用setPosition()方法以编程方式更新标记位置。

    Marker marker = googleMap.addMarker(new MarkerOptions().position(entry.getValue()).title(entry.getKey()));
    

    使用此对象更改其位置:

     marker.setPosition(new LatLng(5, 5));
    
  • 或者像你说的那样,利用Handlers:

    Handler locationHandler;
    final static long REFRESH = 10 * 1000;
    final static int SUBJECT = 0;
    private GoogleMap mMap;
    private Marker myMarker = null;
    

    和onCreate()

    locationHandler = new Handler() {
    public void handleMessage(Message msg) {
        if (msg.what == SUBJECT) {
            updateMarker();
            this.sendEmptyMessageDelayed(SUBJECT, REFRESH);
        }
    }
    };
    

在需要在特定时间间隔内更新位置的情况下,处理程序选项更好。


嗯...第一种解决方案不起作用,因为在UI线程上通过删除/添加运行来更新标记,导致我的应用程序崩溃了。 我能否获得更多关于第二种解决方案的解释,以及如何在这种情况下使用处理程序?通过您的代码示例,我真的不知道如何将其集成到我的update(Observable observable,final Object object)方法中。 非常感谢! - QuentR

0

我有类似这样的东西。每5分钟我会收到一个设备列表来更新地图上的位置。

你对此有何看法?

private HashMap<String, Marker> mMarkers = new HashMap<>();    

private void drawDevicesOnMap() {
            if (isMapReady) {
                for (Device device : mDeviceList) {

                    List<com.model.Location> locationList = device.getLocations();

                    if (locationList != null && !locationList.isEmpty()) {
                        if (mMarkers.containsKey(device.getId())) {  //update
                            Marker m = mMarkers.get(device.getId());
                            m.setPosition(device.getLocations().get(0).getCoordinates().getLatLng());
                            mMarkers.put(device.getId(), m);
                        } else { //add
                            MarkerOptions markerOptions = new MarkerOptions();
                            markerOptions.position(locationList.get(0).getCoordinates().getLatLng());
                            markerOptions.icon(BitmapDescriptorFactory.defaultMarker(device.getHue()));
                            markerOptions.title(device.getNickname());
                            Marker marker = mMap.addMarker(markerOptions);
                            mMarkers.put(device.getId(), marker);
                        }
                    }
                }
            }
        }

如果在HashMap中找到了具有x ID的设备的标记,则更新其位置。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接