我最近开发了一个html5移动应用程序。该应用程序是单个页面,其中导航哈希更改事件替换整个DOM。该应用程序的一部分是使用API v3的Google Map。在从DOM中删除map div之前,我想删除任何事件处理程序/侦听器并释放尽可能多的内存,因为用户可能不会再次返回该部分。
销毁地图实例的最佳方法是什么?
答案 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)
因为显然你无法真正破坏地图实例,所以如果
可以减少这个问题保留了一组地图实例。 该池保留正在使用的实例的跟踪,当它被请求一个新实例时,它检查是否有任何可用的映射实例是空闲的:如果是,它将返回一个现有的实例,如果不是,它将创建一个新的地图实例并将其返回,将其添加到池中。这样,您将只有最大数量的实例等于您在屏幕上同时显示的最大地图数。 我使用这段代码(它需要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
删除有关事件(delete
,addEventListener
等)的属性(仍然有一个数组它存储添加的事件的地方。)null
以避免IE 6/7/8内存泄漏。