Aggiornamento dal agosto 2016
Sintesi il corretta risposta ora per questo problema è quello di utilizzare la nuova onCameraIdle
, invece di OnCameraChangeListener
, che ora è deprecated. Leggi sotto come.
Ora puoi ascoltare l'evento "dragEnd" -like e anche altri eventi sulla versione più recente di Google Maps per Android.
Come mostrato nella docs, è possibile evitare il problema della multipla (alias "diversi") chiamate del OnCameraChangeListener
utilizzando i nuovi ascoltatori. Ad esempio, ora sei in grado di verificare qual è il motivo dietro il movimento della telecamera, che è l'ideale per accoppiare con un problema fetchData
come richiesto. Il seguente codice è per lo più preso direttamente dai documenti. Ancora una cosa, è necessario utilizzare 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);
// Show Sydney on the map.
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)
}
}
Soluzione per una soluzione efficace prima di agosto 2016
Dato che la questione sia adeguatamente risolta, vorrei aggiungere che in una probabilità di essere prossimo numero.
Il problema si pone quando si utilizza OnCameraChangeListener
per recuperare i dati dal server a causa della frequenza con cui questo metodo viene attivato.
C'è un issue riferito su come all'impazzata frequente questo metodo viene trigged quando si fa una semplice mappa di scorrimento, quindi nell'esempio della questione, sarebbe innescare fetchData
più volte in sequenza per molto piccoli cambiamenti della macchina fotografica, anche per nessuna modifica della fotocamera , sì, succede che i limiti della telecamera non sono cambiati, ma il metodo viene attivato.
Questo potrebbe influire sulle prestazioni lato server e sprecherebbe molte risorse dei dispositivi recuperando i dati in sequenza decine di volte dal server.
È possibile trovare in questo collegamento soluzioni alternative per questo problema, ma non esiste ancora un modo ufficiale per farlo, ad esempio utilizzando i callback desiderabili dragEnd
o cameraChangeEnd
.
Un esempio qui sotto, basato su quelli da lì, è come evito il suddetto problema giocando con l'intervallo di tempo delle chiamate e scartando le chiamate con gli stessi limiti.
// Keep the current camera bounds
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;
// Check whether the camera changes report the same boundaries (?!), yes, it happens
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;
}
Molto bene! Questo probabilmente mi ha permesso di risparmiare parecchie ore di comprensione del lavoro e quindi di risolvere questo problema. Grazie! – EZDsIt
@EZDsIt sei il benvenuto! – Eduardo
Si dovrebbe anche verificare la presenza di 'null' per il campo' currentCameraBounds'. –