什么是破坏地图实例的正确方法?

时间:2012-05-07 16:23:37

标签: javascript google-maps-api-3

我最近开发了一个html5移动应用程序。该应用程序是单个页面,其中导航哈希更改事件替换整个DOM。该应用程序的一部分是使用API​​ v3的Google Map。在从DOM中删除map div之前,我想删除任何事件处理程序/侦听器并释放尽可能多的内存,因为用户可能不会再次返回该部分。

销毁地图实例的最佳方法是什么?

7 个答案:

答案 0 :(得分:45)

我在这个问题上添加了第二个答案,因为我不想通过对我之前答案的后续评论来回删除。

但我最近发现了一些直接解决您问题的信息,因此我想分享。我不知道你是否意识到这一点,但在Google Maps API Office Hours May 9 2012 Video期间,Google的Chris Broadfoot和Luke Mahe讨论了来自stackoverflow的这个问题。如果您将视频播放设置为12:50,那么就是他们讨论您的问题的部分。

基本上,他们承认这是一个错误,但也补充说他们并不真正支持涉及创建/销毁连续映射实例的用例。他们强烈建议创建一个地图实例,并在任何此类情况下重复使用它。他们还谈到将map设置为null,并明确删除事件侦听器。你表达了对事件监听器的担忧,我认为只要将map设置为null就足够了,但看起来你的关注点是有效的,因为它们特别提到了事件监听器。他们还建议完全删除保存地图的DIV。

无论如何,只是想传递这一点,并确保它包含在stackoverflow讨论中,希望它能帮助你和其他人 -

答案 1 :(得分:25)

official answer不是。应该重用单个页面应用程序中的映射实例,而不是销毁然后重新创建。

对于某些单页面应用程序,这可能意味着重新构建解决方案,以便一旦创建了映射,它可能会被隐藏或与DOM断开连接,但它永远不会被销毁/重新创建。

答案 2 :(得分:12)

因为显然你无法真正破坏地图实例,所以如果

可以减少这个问题
  • 您需要在网站上一次显示多张地图
  • 地图数量可能会随用户互动而变化
  • 地图需要隐藏并与其他组件一起重新显示(即它们不会出现在DOM中的固定位置)

保留了一组地图实例。 该池保留正在使用的实例的跟踪,当它被请求一个新实例时,它检查是否有任何可用的映射实例是空闲的:如果是,它将返回一个现有的实例,如果不是,它将创建一个新的地图实例并将其返回,将其添加到池中。这样,您将只有最大数量的实例等于您在屏幕上同时显示的最大地图数。 我使用这段代码(它需要jQuery):

var mapInstancesPool = {
 pool: [],
 used: 0,
 getInstance: function(options){
    if(mapInstancesPool.used >= mapInstancesPool.pool.length){
        mapInstancesPool.used++;
        mapInstancesPool.pool.push (mapInstancesPool.createNewInstance(options));
    } else { 
        mapInstancesPool.used++;
    }
    return mapInstancesPool.pool[mapInstancesPool.used-1];
 },
 reset: function(){
    mapInstancesPool.used = 0;
 },
 createNewInstance: function(options){
    var div = $("<div></div>").addClass("myDivClassHereForStyling");
    var map =   new google.maps.Map(div[0], options);
    return {
        map: map,
        div: div
    }
 }
}

您将起始地图选项(根据google.maps.Map的构造函数的第二个参数)传递给它,并返回地图实例(您可以在其上调用与google.maps.Map相关的函数) ),以及容器,您可以使用类&#34; myDivClassHereForStyling&#34;来设置样式,并且您可以使用dinamically附加到DOM。 如果需要重置系统,可以使用mapInstancesPool.reset()。它会将计数器重置为0,同时保留池中的所有现有实例以供重用。 在我的应用程序中,我需要一次删除所有地图并创建一组新的地图,因此没有功能来回收特定的地图实例:您的里程可能会有所不同。 要从屏幕上删除地图,我使用jQuery的分离,它不会破坏地图的容器。

使用此系统,并使用

google.maps.event.clearInstanceListeners(window);
google.maps.event.clearInstanceListeners(document);

并正在运行

google.maps.event.clearInstanceListeners(divReference[0]);
divReference.detach()

(其中divReference是从实例池返回的div的jQuery对象) 在我移除的每个div上,我设法保持Chrome的内存使用率或多或少稳定,而不是每次删除地图并添加新地图时都会增加。

答案 3 :(得分:5)

我建议删除map div的内容,并在保存对地图的引用的变量上使用delete,并且可能明确delete任何事件侦听器。

虽然有an acknowledged bug,但这可能无效。

答案 4 :(得分:2)

由于google没有为api v3提供gunload(),所以最好在html中使用iframe,并将map.html指定为此iframe的源代码。使用后将src设为null。这肯定会释放地图消耗的内存。

答案 5 :(得分:1)

当您移除div时,会移除显示面板,地图将消失。要删除地图实例,只需确保您对地图的引用设置为null,并且对地图其他部分的任何引用都设置为null。此时,JavaScript垃圾收集将负责清理,如:How does garbage collection work in JavaScript?

中所述

答案 6 :(得分:0)

我猜你在谈论addEventListener。删除DOM元素时,某些浏览器会泄漏这些事件并且不会删除它们。这就是jQuery在删除元素时做了几件事的原因:

  • 它可以在使用removeEventListener时删除事件。这意味着它将保留一个数组,其中包含在此元素上添加的事件侦听器。
  • onclick不可用时,它会在DOM元素上使用onblur删除有关事件(deleteaddEventListener等)的属性(仍然有一个数组它存储添加的事件的地方。)
  • 它将元素设置为null以避免IE 6/7/8内存泄漏。
  • 然后删除该元素。