3

継承した大規模なアプリケーションで作業しており、いくつかのベストプラクティスの問題が発生しています。

ユーザーがカスタマー編集ページに移動するたびに、新しいプレゼンターが作成され、ビューが設定されます。顧客編集用のメインプレゼンターとメインビューがあります。メインプレゼンターのサブプレゼンターが使用するサブビューもメインビュー内にあります。サブプレゼンター内で、イベントバスにイベントハンドラーを登録します。

私が抱えている問題は、連絡先エディターに2回移動すると、プレゼンターが再度作成され、それらのイベントが再度登録されることです。これで、イベントが発生すると、プレゼンターインスタンスごとに1回ずつ、2回処理されます。

プレゼンターは変数によって保持されませんが、サブビューはメインビューによって参照されます。ビュー内のこの参照が、イベントハンドラーの削除を妨げている可能性がありますか?そのオブジェクトがガベージコレクションされた場合、イベントハンドラーが削除されるという印象を受けました。そうでない場合は、これらのイベントハンドラーをイベントバスから登録解除する必要がありますか?

更新:プレゼンターはガベージコレクションされていません。コードを変更して、それらのプレゼンターへのすべての参照が不要になったときにそれらを削除できる場合、それらは収集されるので、イベントハンドラーは削除されますか?

4

2 に答える 2

5

はこのResettableEventBusために特別に設計されています。プレゼンターにグローバルイベントバスを提供する代わりに、そのイベントバスをリセット可能なバージョンでラップします。次に、そのプレゼンターがシャットダウンされると、そのイベントバスを与えた人は誰でもそれをリセットし、追加した可能性のあるすべてのハンドラーをクリーンアップします。

これは、GWTのActivity / Placeフレームワークのアクティビティを管理して、リークを防ぐ方法です。

別のオプション-各プレゼンターに「stop()」または「release()」のようなメソッドを与えて、それが最上位であり、それ自体の後にモップアップする必要があることを示します-進行中のRPC呼び出しをキャンセルし、ダイアログボックスを削除し、イベントをキャンセルしますハンドラー。上記のように、Activity APIには、停止しようとしていること、および停止してクリーンアップする必要があることを示すメソッドがあります。

両方を提供することで、グローバルイベントバスを間違えないようにすることが容易になり、さらにきめ細かい問題(長時間実行されるRPC呼び出し)にフックを与えることができますが、どちらの解決策でも問題を解決できます。

于 2012-12-06T23:28:07.947 に答える
1

イベント ハンドラーは、EventBus 内のある種のコレクションに対して設定および格納される個別のオブジェクト インスタンスです。プレゼンターはそれらを作成して EventBus に渡すだけなので、ハンドラーはプレゼンターの有効期間を超えて引き続き参照されます (そのため、ハンドラーは実行され続けます)。ハンドラーがまだプレゼンターまたはそのフィールドを参照している可能性があるため、プレゼンターはおそらくガベージ コレクションされていません。

新しいプレゼンターを作成すると、検出されるたびにハンドラーが再度追加されるため、解決策は、新しいプレゼンターをインスタンス化する前に既存のハンドラーをクリアするか、それらを追跡し、既に追加されている場合は新しいハンドラーを追加しないことです。 .

私が取るアプローチは、画面レベルの View/Presenter インスタンスを再利用し、再入力時にその状態をリセットすることです。これはパフォーマンスにも役立ちます。プレゼンターは、EventBus に追加するすべてのハンドラーの HandlerRegistration インスタンスも追跡します。

Colin が言及している ResettableEventBus については知りませんでしたが、それも良い解決策のように思えます。

于 2012-12-06T23:49:23.493 に答える