최근에 html5 모바일 애플리케이션을 개발했습니다. 애플리케이션은 탐색 해시 변경 이벤트가 전체 DOM을 대체하는 단일 페이지였습니다. 애플리케이션의 한 섹션은 API v3를 사용하는 Google지도였습니다. 맵 div가 DOM에서 제거되기 전에 이벤트 핸들러 / 리스너를 제거하고 사용자가 해당 섹션으로 다시 돌아갈 수없는 한 가능한 한 많은 메모리를 확보하고 싶습니다.
맵 인스턴스를 파괴하는 가장 좋은 방법은 무엇입니까?
최근에 html5 모바일 애플리케이션을 개발했습니다. 애플리케이션은 탐색 해시 변경 이벤트가 전체 DOM을 대체하는 단일 페이지였습니다. 애플리케이션의 한 섹션은 API v3를 사용하는 Google지도였습니다. 맵 div가 DOM에서 제거되기 전에 이벤트 핸들러 / 리스너를 제거하고 사용자가 해당 섹션으로 다시 돌아갈 수없는 한 가능한 한 많은 메모리를 확보하고 싶습니다.
맵 인스턴스를 파괴하는 가장 좋은 방법은 무엇입니까?
답변:
이 질문에 대한 두 번째 답변을 추가하고 있습니다. 이전 답변에 대한 후속 의견을 통해 앞뒤로 가졌던 내용을 제거하고 싶지 않기 때문입니다.
하지만 최근에 귀하의 질문을 직접적으로 다루는 몇 가지 정보를 발견했기 때문에 공유하고 싶었습니다. 이 사실을 알고 있는지는 모르겠지만 Google Maps API Office Hours 2012 년 5 월 9 일 비디오 에서 Google의 Chris Broadfoot과 Luke Mahe 는 stackoverflow 에서이 질문에 대해 논의 했습니다 . 비디오 재생을 12:50으로 설정하면이 섹션에서 질문에 대해 논의합니다.
본질적으로 그들은 그것이 버그임을 인정하지만, 연속적인 맵 인스턴스를 생성 / 파괴하는 것과 관련된 사용 사례를 실제로 지원하지 않는다고 덧붙입니다. 지도의 단일 인스턴스를 만들고 이러한 종류의 모든 시나리오에서 재사용 할 것을 강력히 권장합니다. 또한지도를 null로 설정하고 이벤트 리스너를 명시 적으로 제거하는 방법에 대해서도 설명합니다. 이벤트 리스너에 대한 우려를 표명하고 맵을 null로 설정하는 것으로 충분하다고 생각했지만 이벤트 리스너를 구체적으로 언급하기 때문에 우려 사항이 유효한 것 같습니다. 그들은 또한지도를 보유하는 DIV도 완전히 제거 할 것을 권장했습니다.
어쨌든, 이것을 전달하고 그것이 stackoverflow 토론에 포함되어 있는지 확인하고 당신과 다른 사람들에게 도움이되기를 바랍니다.
분명히 맵 인스턴스를 실제로 파괴 할 수 없기 때문에이 문제를 줄이는 방법은 다음과 같습니다.
맵 인스턴스 풀을 유지하고 있습니다. 풀은 사용중인 인스턴스의 추적을 유지하고, 새 인스턴스가 요청되면 사용 가능한 맵 인스턴스가 비어 있는지 확인합니다. 새 맵 인스턴스를 생성하고 반환하여 풀에 추가합니다. 이렇게하면 화면에 동시에 표시 한지도의 최대 수와 동일한 최대 인스턴스 수만 갖게됩니다. 이 코드를 사용하고 있습니다 (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를 사용합니다.
이 시스템을 사용하고
google.maps.event.clearInstanceListeners(window);
google.maps.event.clearInstanceListeners(document);
그리고 달리기
google.maps.event.clearInstanceListeners(divReference[0]);
divReference.detach()
(여기서 divReference는 인스턴스 풀에서 반환 된 div의 jQuery 객체입니다) 제거하는 모든 div에서 Chrome의 메모리 사용량을 어느 정도 안정적으로 유지할 수 있었는데,지도를 삭제하고 새지도를 추가 할 때마다 증가하는 것과는 대조적이었습니다.
지도 div의 내용을 제거하고지도 delete
에 대한 참조를 포함하는 변수를 사용 하고 아마도 delete
모든 이벤트 리스너를 명시 적으로 지정 하는 것이 좋습니다.
이 인정받는 버그는 하지만,이 작동하지 않을 수 있습니다.
delete
가 많은 것을 추가 한다고 생각하지 않지만 ( stackoverflow.com/q/742623/1314132 참조 ) 정말 아프지는 않습니다. 결국이 질문으로 귀결됩니다. 객체에 대한 참조가 있습니까? 그렇다면 가비지 수집되지 않습니다.
GUnload()
모든 API의 내부 참조를 제거해야합니다.
delete
하지 않는다면 실제로 수정이되지는 않습니다. 참조에 도달 할 수 없게 작동하도록 큰 문제를 수정하거나 설명하는 기능을 제공하는 새 기능을 추가해야합니다 GUnload()
.
delete
하고, 삭제 innerHTML
하지 않습니다 완전히 명확한 메모리를. 불행히도 이것은 우선 순위가 높은 버그가 아닙니다.
Google은 api v3에 gunload ()를 제공하지 않으므로 html에서 iframe을 더 잘 사용하고이 iframe에 대한 소스로 map.html을 할당합니다. 사용 후 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
합니다.