次のJavaコードを検討してください
public class PlayerView implements IPlayerListener
{
public Player player;
public PlayerView()
{
player = new Player();
player.listener = this;
}
public void onPlayerEvent()
{
}
}
public class Player
{
public IPlayerListener listener;
public void foo()
{
//do something then
if(this.listener != null)
{
this.listener.onPlayerEvent();
}
}
}
public interface IPlayerListener
{
public void onPlayerEvent();
}
ここに PlayerView と Player があります。Player はイベントを PlayerView に報告する必要があるため、IPlayerListener というインターフェイスを作成しました。これにより、Player は、イベントを報告する PlayerListener オブジェクトの参照を持つことができます。
(Javaでは、これがイベントを作成する最良の方法ではないことを知っていますが、デフォルトの「addEventListener」パターンを使用するために「多くのリスナー」は必要ありません)
質問 #1: PlayerView オブジェクトが null に設定されている場合、PlayerView と Player オブジェクトの両方が GC によって収集されますか?
はいの場合は、次のコードに進みます
public class PlayerView implements IPlayerListener, IPlaylistListener
{
public Player player;
public PlayerView()
{
player = new Player();
player.listener = this;
player.playlist = new Playlist();
player.playlist.listener = this;
}
public void onPlayerEvent()
{
}
public void onPlaylistEvent()
{
}
}
public class Player
{
public Playlist playlist;
public IPlayerListener listener;
public void foo()
{
//do something then
if(this.listener != null)
{
this.listener.onPlayerEvent();
}
}
}
public class Playlist
{
public IPlaylistListener listener;
public void bar()
{
//do something then
if(this.listener != null)
{
this.listener.onPlaylistEvent();
}
}
}
public interface IPlayerListener
{
public void onPlayerEvent();
}
public interface IPlaylistListener
{
public void onPlaylistEvent();
}
ここでは、3 番目のクラスである Playlist クラスを追加しました。このクラスは、Player にもプレイリスト オブジェクトへの参照があります。また、プレイリストにはリスナー/オブザーバーが必要です。この場合、PlayerView は Playlist リスナーでもあります。
質問 #2: PlayerView オブジェクトが null に設定されている場合、これらのオブジェクトは GC によって収集されますか?
答え #2 が NO の場合は、続行してください
public class PlayerView implements IPlayerListener, IPlaylistListener
{
public Player player;
public PlayerView()
{
player = new Player();
player.listener = this;
player.playlist = new Playlist();
player.playlist.parentPlayer = player;
}
public void onPlayerEvent()
{
}
public void onPlaylistEvent()
{
}
}
public class Player
{
public Playlist playlist;
public IPlayerListener listener;
public void foo()
{
//do something then
if(this.listener != null)
{
this.listener.onPlayerEvent();
}
}
}
public class Playlist
{
public Player parentPlayer;
public void bar()
{
//do something then
if(this.parentPlayer != null)
{
if(this.parentPlayer.listener != null)
{
if(this.parentPlayer.listener instanceof IPlaylistListener)
{
((IPlaylistListener) this.parentPlayer.listener).onPlaylistEvent();
}
}
}
}
}
public interface IPlayerListener
{
public void onPlayerEvent();
}
public interface IPlaylistListener
{
public void onPlaylistEvent();
}
ここでは、playlistListener 参照を親 Player への参照に切り替え、playlistListener を直接呼び出す代わりに、playerListener も PlaylistListener であるかどうかを確認します (または、両方のインターフェイスを 1 つにマージできます)。
質問 #3: 前のコードで問題が解決し、すべてのオブジェクトが収集されますか?
または、2 番目のコード ブロックを使用して、PlayerView オブジェクトで適切な時間を見つけ (PlayerView オブジェクトが親ビューから削除される前など)、少なくとも "player.playlist.listener = null;" を呼び出す必要があります。