最近、html5モバイルアプリケーションを開発しました。アプリケーションは、ナビゲーションハッシュ変更イベントがDOM全体を置き換えた単一のページでした。アプリケーションの1つのセクションは、APIv3を使用したGoogleマップでした。map divがDOMから削除される前に、イベントハンドラー/リスナーを削除し、ユーザーがそのセクションに再び戻らないように、できるだけ多くのメモリを解放したいと思います。
マップインスタンスを破棄する最良の方法は何ですか?
最近、html5モバイルアプリケーションを開発しました。アプリケーションは、ナビゲーションハッシュ変更イベントがDOM全体を置き換えた単一のページでした。アプリケーションの1つのセクションは、APIv3を使用したGoogleマップでした。map divがDOMから削除される前に、イベントハンドラー/リスナーを削除し、ユーザーがそのセクションに再び戻らないように、できるだけ多くのメモリを解放したいと思います。
マップインスタンスを破棄する最良の方法は何ですか?
回答:
以前の回答に対するフォローアップコメントを介して行った前後を削除したくないので、この質問に2番目の回答を追加します。
しかし、最近、あなたの質問に直接対処するいくつかの情報に出くわしたので、共有したいと思いました。これをご存知かどうかはわかりませんが、2012年5月9日のGoogle Maps APIオフィスアワーのビデオで、GoogleのChrisBroadfootとLukeMaheが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のデタッチを使用します。これはマップのコンテナを破壊しません。
このシステムを使用して、
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
てもメモリは完全にはクリアされません。残念ながら、これは優先度の高いバグではありません。
グーグルはapiv3に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
IE6 / 7/8のメモリリークを回避するように要素を設定します。removeEventListener
またはそれにdelete
応じて手動で削除します。