最近、html5モバイルアプリケーションを開発しました。アプリケーションは、ナビゲーションハッシュ変更イベントがDOM全体を置き換えた単一のページでした。アプリケーションの1つのセクションは、APIv3を使用したGoogleマップでした。マップdivがDOMから削除される前に、イベントハンドラー/リスナーを削除し、ユーザーがそのセクションに再び戻らないように、できるだけ多くのメモリを解放したいと思います。
マップインスタンスを破棄する最良の方法は何ですか?
最近、html5モバイルアプリケーションを開発しました。アプリケーションは、ナビゲーションハッシュ変更イベントがDOM全体を置き換えた単一のページでした。アプリケーションの1つのセクションは、APIv3を使用したGoogleマップでした。マップdivがDOMから削除される前に、イベントハンドラー/リスナーを削除し、ユーザーがそのセクションに再び戻らないように、できるだけ多くのメモリを解放したいと思います。
マップインスタンスを破棄する最良の方法は何ですか?
この質問に 2 番目の回答を追加します。これは、以前の回答に対するフォローアップ コメントで行ったやり取りを削除したくないためです。
しかし、最近、あなたの質問に直接対応する情報に出くわしたので、共有したいと思いました. あなたがこれを認識しているかどうかはわかりませんが、Google Maps API Office Hours 2012 年 5 月 9 日のビデオで、Google の Chris Broadfoot と Luke Mahe が、stackoverflow からのまさにこの質問について議論しました。ビデオの再生を 12:50 に設定すると、そのセクションで質問について話し合うことができます。
基本的に、彼らはこれがバグであることを認めていますが、連続するマップ インスタンスの作成/破棄を伴うユース ケースを実際にはサポートしていないとも付け加えています。マップの単一インスタンスを作成し、この種のシナリオで再利用することを強くお勧めします。また、マップを null に設定し、イベント リスナーを明示的に削除することについても説明しています。イベントリスナーに関する懸念を表明しました。マップを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 のコンストラクターの 2 番目の引数に従って) 開始マップ オプションを渡すと、マップ インスタンス (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
イベント リスナーを明示的に ing することをお勧めします。
ただし、既知のバグがあり、これが機能しない場合があります。
Google は api v3 用の gunload() を提供していないため、html で iframe を使用し、map.html をソースとしてこの iframe に割り当てます。使用後、srcをnullにします。これにより、マップによって消費されたメモリが確実に解放されます。
を削除するdiv
と、表示パネルが削除され、マップが消えます。マップインスタンスを削除するには、マップへの参照がに設定されnull
ていること、およびマップの他の部分への参照がに設定されていることを確認してくださいnull
。その時点で、「JavaScriptでガベージコレクションはどのように機能しますか?」で説明されているように、JavaScriptガベージコレクションがクリーンアップを処理します。。
私はあなたが話していると思いますaddEventListener
。DOM要素を削除すると、一部のブラウザーはこれらのイベントをリークし、削除しません。これが、要素を削除するときにjQueryがいくつかのことを行う理由です。
removeEventListener
。これは、この要素に追加したイベントリスナーとの配列を保持していることを意味します。onclick
、onblur
など)に関する属性を削除します(それでも、追加されたイベントを格納する配列があります)。delete
addEventListener
null
IE6/7/8のメモリリークを回避するように要素を設定します。