刷新GoogleMaps磁贴服务器在JavaScript中工作,但在GWT中不工作

Kev*_*man 9 javascript java gwt google-maps

我正在GWT应用程序中显示天气图.我使用GWT 2.7和可用的GoogleMaps的JavaScript API的GWT包装这里(gwt-maps-3.8.0-pre1.zip).

我使用磁贴服务器来获取天气,每5分钟更新一次.在5分钟标记处,我通过将缩放设置为1然后返回到原始图像来刷新地图,方法是触发调整大小,然后再次删除然后再添加天气图层.

这很好.但是,最近我注意到这不再起作用:刷新甚至不会进入磁贴服务器,因此不会显示新的天气.如果你把地图放了12个小时,你会看到12个小时的天气.以前,地图会自动保持更新.我没有改变任何代码.所以我的猜测是底层的GoogleMaps JavaScript API发生了变化.

但是,我创建了这个简单的纯JavaScript示例:

<!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>
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,这仍然很好.每当您单击"刷新"按钮时,地图将转到切片服务器并获取新切片.

所以我尝试在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);
    }-*/;

}
Run Code Online (Sandbox Code Playgroud)

这应该与纯JavaScript示例相同.相反,当我单击按钮时,地图会刷新(我看到天气层闪烁),但它实际上并没有转到瓷砖服务器以获取新的切片.

更奇怪的是,这个"sorta"在Internet Explorer中工作:我点击按钮时可能有3次,地图实际上会转到磁贴服务器.但是在Chrome中,当我点击按钮时它永远不会进入磁贴服务器.

为了确定这一点,我正在查看浏览器工具的网络选项卡.我希望每次单击按钮时地图都会点击磁贴服务器.这就是它在纯JavaScript中的作用,而这正是它在GWT中所做的,但在过去几个月的某个时候,GWT的行为发生了变化.

我不认为这是一个浏览器缓存问题.问题在于地图试图获取新的瓷砖而是获取新的瓷砖,而是它永远不会尝试获取新的瓷砖.我单击按钮,我看到开发人员工具的网络选项卡中没有发生任何事情.

  • 为什么我在JavaScript和GWT中看到不同的行为?
  • 为什么我在不同的浏览器中看到不同的行为?
  • GWT GoogleMaps库是否正在进行某种内部缓存?有没有办法禁用它?
  • 为什么这种行为明显改变了?
  • 如何通过转到磁贴服务器以获取新磁贴来刷新GWT映射?

fho*_*ann 1

这不是最终答案。但包含重要信息。

为了管理 http 调用,GWT 有一组类似于浏览器的类,我认为这就是问题所在。

如果相同的代码之前可以工作,则瓦片服务器最近可能包含缓存标头(Cache-Control:max-age=300)。由于某种原因,GWT 代码无法正确管理此标头。

如果我是对的,解决该问题的一种方法是在 GWT 调用中附加一个包含当前时间的参数(例如代码的浏览器版本)。

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?" + new Date().getTime();
        },
        tileSize: new $wnd.google.maps.Size(256, 256),
        opacity:.50,
        isPng: true
    });

    map.overlayMapTypes.setAt("0", imageMapType);

}-*/;
Run Code Online (Sandbox Code Playgroud)