刷新多个 Google 个地图标记位置,而不刷新整个地图 Android
Refresh many Google Map markers position, without refresh the whole map in Android
我目前正在开发一个 Android 应用程序,它必须每分钟从其他设备接收 GPS 位置,并将其显示在地图上。
我正在使用 GoogleMaps Api V2,
我想做的是在收到新位置时立即刷新位置标记。 (我不想刷新整个地图)
目前,我在菜单中添加了一个按钮,使我能够刷新整个地图。
详细结构,我有一个 运行 MQTT 服务,每次收到一个位置,我都会将它添加到一个 Hashmap 中,它代表我的地图数据源。
这个 HashMap 是一个扩展了 Observable 的 Singleton。
此外,我的片段显示我的工具 Observer。
我实现 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();
}
来自 myService 的代码,运行s 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 的更新功能中单独移动每个标记而不刷新整个地图吗?
我可以使用一个处理程序来更新地图,从另一个线程修改主线程 UI 吗?
非常感谢
编辑:
因为 AniV 给出的第一个方法对我不起作用,所以我尝试使用 Asyntask,当我的观察者从 Observable List 收到通知时 运行s。
来自观察者片段的代码:
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);
}
但是,在这种情况下,我的Google地图变量始终为空,因此永远不会将标记添加到 Google 地图。
有人知道为什么这个变量为空吗?
这里有两个选择:
要么使用 setPosition() 方法以编程方式更新标记位置。
Marker marker = googleMap.addMarker(new MarkerOptions().position(entry.getValue()).title(entry.getKey()));
使用此对象更改其位置:
marker.setPosition(new LatLng(5, 5));
或者如您所说,使用处理程序:
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);
}
}
};
在必须以特定时间间隔更新位置的情况下,处理程序选项更好。
我终于通过使用 AsyncTask 成功地完成了那件事。
在我的编辑中,我说我的 Google Maps 对象的空实例有一些问题。
这是由我的 Singleton Observable 引起的。实际上,在构造函数中,我使用了
VehicleMapFragment mapFragmentObserver = new VehicleMapFragment();
this.addObserver(mapFragmentObserver);
此代码示例重新创建了我的 Fragment 的另一个实例,这就是 ii 具有 Null 对象的原因。
为了纠正这个问题,我简单地使用了:
ListPositions.getInstance().addObserver(this);
在我的 Fragment Observer 中。
所以如果你想在不刷新整个地图的情况下更新标记位置,
您可以使用 Observer/Observable 模式,并使用 Asynctask 更新标记位置。
我有这样的东西。我每 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 的设备标记,则更新其位置。
我目前正在开发一个 Android 应用程序,它必须每分钟从其他设备接收 GPS 位置,并将其显示在地图上。 我正在使用 GoogleMaps Api V2,
我想做的是在收到新位置时立即刷新位置标记。 (我不想刷新整个地图)
目前,我在菜单中添加了一个按钮,使我能够刷新整个地图。
详细结构,我有一个 运行 MQTT 服务,每次收到一个位置,我都会将它添加到一个 Hashmap 中,它代表我的地图数据源。 这个 HashMap 是一个扩展了 Observable 的 Singleton。 此外,我的片段显示我的工具 Observer。
我实现 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();
}
来自 myService 的代码,运行s 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 的更新功能中单独移动每个标记而不刷新整个地图吗? 我可以使用一个处理程序来更新地图,从另一个线程修改主线程 UI 吗?
非常感谢
编辑:
因为 AniV 给出的第一个方法对我不起作用,所以我尝试使用 Asyntask,当我的观察者从 Observable List 收到通知时 运行s。
来自观察者片段的代码:
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);
}
但是,在这种情况下,我的Google地图变量始终为空,因此永远不会将标记添加到 Google 地图。
有人知道为什么这个变量为空吗?
这里有两个选择:
要么使用 setPosition() 方法以编程方式更新标记位置。
Marker marker = googleMap.addMarker(new MarkerOptions().position(entry.getValue()).title(entry.getKey()));
使用此对象更改其位置:
marker.setPosition(new LatLng(5, 5));
或者如您所说,使用处理程序:
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); } } };
在必须以特定时间间隔更新位置的情况下,处理程序选项更好。
我终于通过使用 AsyncTask 成功地完成了那件事。
在我的编辑中,我说我的 Google Maps 对象的空实例有一些问题。 这是由我的 Singleton Observable 引起的。实际上,在构造函数中,我使用了
VehicleMapFragment mapFragmentObserver = new VehicleMapFragment();
this.addObserver(mapFragmentObserver);
此代码示例重新创建了我的 Fragment 的另一个实例,这就是 ii 具有 Null 对象的原因。
为了纠正这个问题,我简单地使用了:
ListPositions.getInstance().addObserver(this);
在我的 Fragment Observer 中。
所以如果你想在不刷新整个地图的情况下更新标记位置, 您可以使用 Observer/Observable 模式,并使用 Asynctask 更新标记位置。
我有这样的东西。我每 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 的设备标记,则更新其位置。