自2016年8月以来的更新
概述:现在这个问题的正确答案是使用新的onCameraIdle
,而不是现在已弃用的OnCameraChangeListener
。请阅读下面的内容。
现在你可以在最新版本的Google Maps for Android上监听“dragEnd”等事件,甚至其他事件。
如文档所示,您可以通过使用新的侦听器来避免OnCameraChangeListener
多次(也称为“几次”)调用的问题。例如,现在您能够检查相机移动背后的原因,这是与请求的fetchData
问题相结合的理想选择。以下代码大部分直接来自文档。还有一件事,必须使用Google Play Services 9.4。
public class MyCameraActivity extends FragmentActivity implements
OnCameraMoveStartedListener,
OnCameraMoveListener,
OnCameraMoveCanceledListener,
OnCameraIdleListener,
OnMapReadyCallback {
private GoogleMap mMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_camera);
SupportMapFragment mapFragment =
(SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap map) {
mMap = map;
mMap.setOnCameraIdleListener(this);
mMap.setOnCameraMoveStartedListener(this);
mMap.setOnCameraMoveListener(this);
mMap.setOnCameraMoveCanceledListener(this);
mMap.moveCamera(CameraUpdateFactory
.newLatLngZoom(new LatLng(-33.87365, 151.20689), 10));
}
@Override
public void onCameraMoveStarted(int reason) {
if (reason == OnCameraMoveStartedListener.REASON_GESTURE) {
Toast.makeText(this, "The user gestured on the map.",
Toast.LENGTH_SHORT).show();
} else if (reason == OnCameraMoveStartedListener
.REASON_API_ANIMATION) {
Toast.makeText(this, "The user tapped something on the map.",
Toast.LENGTH_SHORT).show();
} else if (reason == OnCameraMoveStartedListener
.REASON_DEVELOPER_ANIMATION) {
Toast.makeText(this, "The app moved the camera.",
Toast.LENGTH_SHORT).show();
}
}
@Override
public void onCameraMove() {
Toast.makeText(this, "The camera is moving.",
Toast.LENGTH_SHORT).show();
}
@Override
public void onCameraMoveCanceled() {
Toast.makeText(this, "Camera movement canceled.",
Toast.LENGTH_SHORT).show();
}
@Override
public void onCameraIdle() {
Toast.makeText(this, "The camera has stopped moving. Fetch the data from the server!", Toast.LENGTH_SHORT).show();
LatLngBounds bounds = mMap.getProjection().getVisibleRegion().latLngBounds;
fetchData(bounds)
}
}
在2016年8月之前寻找高效解决方案的解决方法
问题已经得到妥善解答,我想补充一下可能出现的下一个问题。
当使用OnCameraChangeListener
从服务器获取数据时,由于此方法被触发的频率,问题就会出现。
有一个问题报告表明,在进行简单的地图滑动时,该方法被触发的频率非常高,因此在问题的示例中,它将为非常少的相机更改甚至没有相机更改多次触发fetchData
,是的,摄像头范围没有改变,但该方法仍然被触发。
这可能会影响服务器端性能,并且会浪费大量设备资源,从服务器顺序获取数据十几次。
您可以在该链接中找到解决此问题的解决方法,但尚没有官方方法来解决它,例如使用理想的dragEnd
或cameraChangeEnd
回调。
下面是一个例子,基于这些例子,我通过调整调用的时间间隔并且筛除具有相同范围的调用来避免上述问题。
private LatLngBounds currentCameraBounds;
new GoogleMap.OnCameraChangeListener() {
private static int CAMERA_MOVE_REACT_THRESHOLD_MS = 500;
private long lastCallMs = Long.MIN_VALUE;
@Override
public void onCameraChange(CameraPosition cameraPosition) {
LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds;
if (currentCameraBounds.northeast.latitude == bounds.northeast.latitude
&& currentCameraBounds.northeast.longitude == bounds.northeast.longitude
&& currentCameraBounds.southwest.latitude == bounds.southwest.latitude
&& currentCameraBounds.southwest.longitude == bounds.southwest.longitude) {
return;
}
final long snap = System.currentTimeMillis();
if (lastCallMs + CAMERA_MOVE_REACT_THRESHOLD_MS > snap) {
lastCallMs = snap;
return;
}
fetchData(bounds);
lastCallMs = snap;
currentCameraBounds = bounds;
}
mMap.getProjection()
或mMap.getVisibleRegion()
。 - capdragon