Wyświetlam mapę pogodową w aplikacji GWT. Używam GWT 2.7 i opakowania GWT API API GoogleMaps dostępnego pod numerem here (gwt-maps-3.8.0-pre1.zip).Odświeżający serwer kafli GoogleMaps działa w JavaScript, ale nie w GWT
Używam serwera kaflowego do pobierania prognozy pogody co 5 minut. Po 5 minutach odświeżam mapę, ustawiając zoom na 1, a następnie z powrotem do oryginału, uruchamiając zmianę rozmiaru i usuwając, a następnie ponownie dodając warstwę meteorologiczną.
To zadziałało dobrze. Jednak ostatnio zauważyłem, że to już nie działa: odświeżanie nigdy nie idzie nawet do serwera kafelków, więc nie wyświetla się nowa pogoda. Jeśli opuścisz moją mapę o 12 godzin, zobaczysz pogodę, która ma 12 godzin. Wcześniej mapa była automatycznie aktualizowana. Nie zmieniłem żadnego z moich kodów. Domyślam się, że coś zmieniło się w bazowym interfejsie API JavaScript GoogleMaps.
Jednak potem stworzył ten prosty przykład JavaScriptu czystego:
<!DOCTYPE html>
<html>
<head>
<title>Map Test</title>
<style type="text/css">
html, body { height: 100%; margin: 0; padding: 0; }
#map {
width:90%;
height: 90%;
display:inline-block;
}
</style>
</head>
<body>
<div id="map"></div>
<button type="button" onClick="refreshMap()">Refresh</button>
<script type="text/javascript">
var map;
var tileNEX;
function initMap() {
var mapOptions = {
zoom: 8,
center: new google.maps.LatLng(42.5, -95.5),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map'), mapOptions);
tileNEX = new google.maps.ImageMapType({
getTileUrl: function(tile, zoom) {
return "http://mesonet.agron.iastate.edu/cache/tile.py/1.0.0/nexrad-n0q-900913/" + zoom + "/" + tile.x + "/" + tile.y +".png?"+ (new Date()).getTime();
},
tileSize: new google.maps.Size(256, 256),
opacity:0.60,
name : 'NEXRAD',
isPng: true
});
map.overlayMapTypes.setAt("0",tileNEX);
}
function refreshMap(){
var zoom = map.getZoom();
map.setZoom(1);
map.setZoom(zoom);
//google.maps.event.trigger(map, 'resize');
//var layer = map.overlayMapTypes.getAt(0);
//map.overlayMapTypes.setAt(0, null);
//map.overlayMapTypes.setAt(0, layer);
}
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap">
</script>
</body>
</html>
Ku mojemu zaskoczeniu, to nadal działa dobrze. Po kliknięciu przycisku Odśwież mapa przechodzi do serwera kafelków i pobiera nowe kafelki.
Więc próbowałem robić dokładnie to samo w GWT:
package com.example.client;
import com.google.gwt.ajaxloader.client.AjaxLoader;
import com.google.gwt.ajaxloader.client.AjaxLoader.AjaxLoaderOptions;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.dom.client.Document;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.maps.gwt.client.GoogleMap;
import com.google.maps.gwt.client.LatLng;
import com.google.maps.gwt.client.MapOptions;
import com.google.maps.gwt.client.MapType;
import com.google.maps.gwt.client.MapTypeId;
public class GwtMapTest implements EntryPoint {
@Override
public void onModuleLoad() {
AjaxLoaderOptions options = AjaxLoaderOptions.newInstance();
options.setOtherParms("sensor=false");
Runnable callback = new Runnable() {
public void run() {
createMap();
}
};
AjaxLoader.loadApi("maps", "3", callback, options);
}
public void createMap() {
MapOptions mapOpts = MapOptions.create();
mapOpts.setZoom(4);
mapOpts.setCenter(LatLng.create(37.09024, -95.712891));
mapOpts.setMapTypeId(MapTypeId.TERRAIN);
mapOpts.setStreetViewControl(false);
final GoogleMap map = GoogleMap.create(Document.get().getElementById("map_canvas"), mapOpts);
addWeatherLayer(map);
Button button = new Button("Gwt Refresh");
button.addClickHandler(new ClickHandler(){
@Override
public void onClick(ClickEvent event) {
refreshWeatherLayer(map);
}
});
Button nativeButton = new Button("Native Refresh");
nativeButton.addClickHandler(new ClickHandler(){
@Override
public void onClick(ClickEvent event) {
nativeRefreshWeatherLayer(map);
}
});
RootPanel.get().add(button);
RootPanel.get().add(nativeButton);
}
public native void addWeatherLayer(GoogleMap map) /*-{
var imageMapType = new $wnd.google.maps.ImageMapType({
getTileUrl: function(coord, zoom) {
return "http://mesonet.agron.iastate.edu/cache/tile.py/1.0.0/nexrad-n0q-900913/"+ zoom + "/" + coord.x + "/" + coord.y + ".png";
},
tileSize: new $wnd.google.maps.Size(256, 256),
opacity:.50,
isPng: true
});
map.overlayMapTypes.setAt("0", imageMapType);
}-*/;
private void refreshWeatherLayer(GoogleMap map){
double zoom = map.getZoom();
map.setZoom(1);
map.setZoom(zoom);
MapType layer = map.getOverlayMapTypes().getAt(0);
map.getOverlayMapTypes().setAt(0, null);
map.getOverlayMapTypes().setAt(0, layer);
}
private native void nativeRefreshWeatherLayer(GoogleMap map) /*-{
var zoom = map.getZoom();
map.setZoom(1);
map.setZoom(zoom);
$wnd.google.maps.event.trigger(map, 'resize');
var layer = map.overlayMapTypes.getAt(0);
map.overlayMapTypes.setAt(0, null);
map.overlayMapTypes.setAt(0, layer);
}-*/;
}
Należy to zrobić to samo, co na przykład czystej JavaScript. Zamiast tego, gdy klikam przycisk, mapa odświeża (widzę mrugającą warstwę pogody), , ale tak naprawdę nie przechodzi do serwera kafelków dla nowych płytek.
Jeszcze dziwniej, ten "sorta" działa w Internet Explorerze: może 1 na 3 razy kliknę przycisk, mapa faktycznie trafia do serwera kafelków. Ale w Chrome nigdy nie trafia do serwera kafelków po kliknięciu przycisku.
Aby to ustalić, patrzę na kartę sieci narzędzi przeglądarki. Spodziewałbym się, że mapa uderzy w serwer kafli za każdym razem, gdy kliknę przycisk. To jest to, co robi w czystym JavaScript, i to było to, co robił w GWT, ale czasami w ciągu ostatnich kilku miesięcy zmieniło się zachowanie GWT.
Nie sądzę, że jest to problem z buforowaniem przeglądarki. Problem polega na tym, że mapa próbuje pobrać nowe kafelki, ale robi stare, ponieważ nigdy nie próbuje pobrać nowych płytek. Klikam przycisk i nic nie dzieje się na karcie sieci narzędzi programistycznych.
- Dlaczego widzę inne zachowanie w JavaScript vs GWT?
- Dlaczego widzę inne zachowanie w różnych przeglądarkach?
- Czy biblioteka GWT GoogleMaps wykonuje jakieś wewnętrzne buforowanie? Czy istnieje sposób, aby to wyłączyć?
- Dlaczego to zachowanie najwyraźniej się zmieniło?
- Jak mogę odświeżyć mapę GWT, przechodząc do serwera kafelków dla nowych płytek?
Przetestowałem skrypt w obu przeglądarkach i wypróbowałem go na GWT. Jedną z różnic, które znalazłem, jest to, że w przeglądarkach umieszczają znacznik czasu po kafelku (/ZOOM/X/Y.png?TIME). Kod GWT najwyraźniej tego nie robi. W przeglądarce, jeśli godzina jest pominięta, IE pobiera ją z serwera, a Chrome pobiera ją z localcache. Być może zmiana dotyczyła serwera kafelkowego (lub konkretnego serwera proxy), który buforuje kafelek. Czy możesz spróbować zaktualizować żądanie w kodzie GWT z parametrem?? TIME? – fhofmann
@fhofmann To zadziałało, co jest dla mnie zaskakujące. Zwykle dodaje się część '? Time', aby uniknąć pamięci podręcznej przeglądarki, co w tym przypadku nie stanowiło problemu, ponieważ nigdy nie trafiła na serwer, a zatem nawet nie sprawdzała pamięci podręcznej przeglądarki. Wygląda więc na to, że musi być jakieś wewnętrzne buforowanie, ale tylko w wersji GWT, która nie ma dla mnie żadnego sensu. Czy możesz wyjaśnić ** dlaczego ** wersje GWT i JS są inne lub dlaczego funkcja '? Time' działa w GWT? Jeśli chcesz dodać to jako odpowiedź, zdecydowanie to doceniam. –
Właściwie nigdy wcześniej nie używałem GWT. Ale teraz jestem ciekawa, a ja spróbuję znaleźć, jak to działa i gdzie może to być buforowanie. – fhofmann