我最近开发了html5移动应用程序。该应用程序是一个页面,其中导航哈希更改事件替换了整个DOM。该应用程序的一部分是使用API v3的Google Map。在从DOM中删除map div之前,我想删除所有事件处理程序/侦听器并释放尽可能多的内存,因为用户可能不会再次返回该部分。
销毁地图实例的最佳方法是什么?
Answers:
我要在这个问题上添加第二个答案,因为我不想通过对先前答案的后续评论来回删除。
但是我最近遇到了一些直接解决您问题的信息,因此我想分享一下。我不知道您是否知道这一点,但是在Google Maps API办公时间2012年5月9日视频中,来自Google的Chris Broadfoot和Luke Mahe从stackoverflow讨论了这个问题。如果将视频播放设置为12:50,则这是他们讨论问题的部分。
从本质上讲,他们承认这是一个错误,但同时补充说,他们并不真正支持涉及创建/销毁连续地图实例的用例。他们强烈建议创建单个地图实例,并在任何这种情况下重新使用它。他们还讨论将地图设置为null,并显式删除事件侦听器。您表达了对事件侦听器的担忧,我认为仅将map设置为null就足够了,但是看起来您的担忧是有效的,因为它们特别提到了事件侦听器。他们还建议完全删除保存地图的DIV。
无论如何,只是想将其传递并确保它已包含在stackoverflow讨论中,并希望它对您和其他人有帮助-
在官方的回答是你不知道。单页应用程序中的地图实例应被重用,并且不被销毁然后重新创建。
对于某些单页应用程序,这可能意味着重新架构解决方案,以便一旦创建地图,就可以将其隐藏或与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有关的函数)和容器(您可以使用“ myDivClassHereForStyling”类设置样式,并且可以动态地附加到DOM。如果需要重置系统,则可以使用mapInstancesPool.reset()。它将计数器重置为0,同时保留池中所有现有实例以供重用。在我的应用程序中,我需要立即删除所有地图并创建一组新地图,因此没有回收特定地图实例的功能:您的行驶里程可能会有所不同。为了从屏幕上删除地图,我使用jQuery的detach,它不会破坏地图的container。
通过使用该系统,并使用
google.maps.event.clearInstanceListeners(window);
google.maps.event.clearInstanceListeners(document);
并运行
google.maps.event.clearInstanceListeners(divReference[0]);
divReference.detach()
(其中divReference是从实例池返回的div的jQuery对象)在我要删除的每个div上,我设法使Chrome的内存使用或多或少保持稳定,而不是每次删除地图和添加新地图时都会增加。
我本来建议删除map div的内容,并delete
在持有对地图的引用的变量上使用,并且可能显式地delete
调用任何事件侦听器。
但是,存在一个已确认的错误,这可能无法正常工作。
delete
增加太多(请参阅stackoverflow.com/q/742623/1314132),但这确实不会造成伤害。最后,归结为这个问题:是否有对该对象的引用?如果是,则不会进行垃圾收集。
GUnload()
删除所有API的内部引用。
delete
这实际上不是解决方法。他们必须解决一些大问题,以使引用无法正常工作,或者添加一个新功能来提供您描述的功能GUnload()
。
delete
并且清除innerHTML
内存并不能完全清除内存。不幸的是,这不是一个高优先级的错误。
由于google不为api v3提供gunload(),因此最好在html中使用iframe并将map.html分配为该iframe的源。使用后,使src为null。那肯定会释放地图消耗的内存。
删除时div
,将删除显示面板,地图将消失。要删除地图实例,只需确保将对地图的引用设置为,null
并将对地图其他部分的所有引用设置为null
。届时,JavaScript垃圾收集将负责清理工作,如以下内容所述:垃圾收集如何在JavaScript中工作?。
null
,还应引用其他任何内容。因此,如果标记引用设置为null
,使其无法访问,则无法访问事件侦听器。它可能仍然连接到地图,但是无法访问地图,因此实际上只是孤立的一个大块内存。与设置Array.length = 0
; 如果没有其他对成员的引用,则它们仅构成一组可以进行垃圾回收的孤立内存。
我猜你在说什么addEventListener
。当您删除DOM元素时,某些浏览器会泄漏这些事件,而不会将其删除。这就是为什么jQuery在删除元素时会做几件事的原因:
removeEventListener
。这意味着它将与添加到此元素的事件侦听器保持数组。onclick
,它将删除事件(,onblur
等)的属性(仍然有一个数组,用于存储添加的事件)。delete
addEventListener
null
为避免IE 6/7/8内存泄漏。removeEventListener
或delete
根据事件类型手动删除。