プレーヤーライフサイクル戦略は、AliPlayerKit のコアアーキテクチャ設計です。プレーヤーインスタンスの作成、再利用、リサイクル、破棄の管理を統合し、さまざまなビジネスシナリオにおいて、より効率的なリソーススケジューリングとパフォーマンスの最適化を可能にします。
はじめに
プレーヤーライフサイクル戦略とは
プレーヤーライフサイクル戦略は、プレーヤーインスタンスのライフサイクルを管理するためのアーキテクチャ上の仕組みです。プレーヤーインスタンスの取得、再利用、クリアなどのコア操作を定義します。これにより、プレーヤーのリソース管理とビジネスロジックが疎結合になります。
ビジネスシナリオごとに、プレーヤーインスタンスの管理に対する要件は異なります。
シナリオ | 要件 | 推奨される戦略 |
通常の動画再生 | シンプルで直接的、再利用は不要 | デフォルト |
ショート動画リスト | 頻繁な切り替え、高速起動が必要 | ReusePool |
動画のプリロード | ID とインスタンスをバインドし、プリロードをサポート | IdScopedPool |
メモリ使用量が重視されるシナリオ | 単一のグローバルインスタンスでメモリフットプリントを最小化 | シングルトン |
主な利点
ストラテジーパターンを使用してプレーヤーのライフサイクルを管理することにより、以下のコアとなる利点が得られます。
疎結合: ビジネスロジックでは、プレーヤーインスタンスの作成と破棄の詳細を処理する必要がありません。
柔軟性: ビジネスロジックを変更することなく、ランタイム時に異なる戦略を選択できます。
拡張性: 特定のビジネスニーズを満たすために、カスタムポリシーを実装できます。
可観測性: 統一されたライフサイクル管理により、モニタリングとデバッグが簡素化されます。
設計の背景
プレーヤーライフサイクル戦略は、Alibaba Cloud のショートドラマソリューションにおけるマルチインスタンスプレーヤープールに由来します。これは、高速スクロールフィードにおける最初のフレームまでの時間 (TTFF)、スムーズな切り替え、メモリ制御に対する厳格な要件を満たすように設計されました。AliPlayerKit は、この手法をストラテジーパターンに抽象化し、プレーヤーのライフサイクルを管理するための、より汎用的で柔軟なアーキテクチャを構築しました。
機能
コア機能
機能 | 説明 |
インスタンスの取得 |
|
インスタンスのリサイクル |
|
リソースのクリーンアップ |
|
プリロード |
|
ID バインディング |
|
ファクトリインジェクション |
|
組み込みストラテジー
AliPlayerKit は、4 つの組み込みプレーヤーライフサイクルストラテジーを提供します。
ストラテジー | クラス名 | 説明 | シナリオ |
デフォルトストラテジー |
| 毎回新しいインスタンスを作成します。使用直後に破棄します。 | 通常再生 |
再利用プールストラテジー |
| アイドルプールを維持します。まずプールからインスタンスを再利用します。 | ショート動画リスト |
ID バインディングポリシー |
| uniqueId ごとに個別のインスタンスを維持します。LRU (Least Recently Used) アルゴリズムを使用してインスタンスを削除します。 | 動画プリロード |
シングルトンストラテジー |
| 単一のグローバルインスタンスです。すべての取得リクエストは同じインスタンスを返します。 | リスト再生、メモリセンシティブなシナリオ |
アーキテクチャレイヤー
┌──────────────────────────────────────────────────────────────┐
│ AliPlayerController │
│ initWithLifecycleStrategy: ストラテジーをインジェクションします │
│ configure: 内部で recycle(old) + acquire(new) を呼び出します │
│ destroy: 内部で recycle(player, force:YES) を呼び出します │
├──────────────────────────────────────────────────────────────┤
│ PlayerLifecycleStrategy プロトコル │
│ setupWithFactory: / acquirePlayer / recyclePlayer:force: │
│ clear / preloadWithCount: / acquirePlayerWithUniqueId: │
├──────────────────────────────────────────────────────────────┤
│ BaseLifecycleStrategy 基底クラス │
│ factory / createPlayer / destroyPlayer: │
├──────────┬──────────┬─────────────────┬──────────────────────┤
│ Default │ReusePool │ IdScopedPool │ Singleton │
│ 毎回新規作成 │ プールの再利用 │ ID バインディング + LRU │ グローバルシングルトン │
└──────────┴──────────┴─────────────────┴──────────────────────┘
│ │
│ PlayerFactory プロトコル / DefaultPlayerFactory │
│ createPlayer / destroyPlayer: │
└──────────────────────────────────────────────────────────────┘使用方法
基本的な使用方法 — デフォルトストラテジー
これは、プレーヤーを使用する最も簡単な方法です。追加の設定は不要です。AliPlayerController は、デフォルトで DefaultLifecycleStrategy を使用します:
// コントローラーを作成します。デフォルトストラテジーが自動的に使用されます。
AliPlayerController *controller = [[AliPlayerController alloc] init];
// 再生データを作成します。
VideoSource *source = [VideoSource urlSourceWithUrl:@"https://example.com/video.mp4"];
AliPlayerModel *model = [[AliPlayerModel alloc] initWithVideoSource:source];
// コントローラーを設定し、プレーヤービューにアタッチします。
[controller configure:model];
[self.playerView attach:controller];デフォルトストラテジーの動作:acquirePlayer の呼び出しごとに新しいインスタンスが作成されます。recyclePlayer:force: の呼び出しごとにインスタンスは直ちに破棄されます。プールは維持されません。
再利用プールストラテジー (ショート動画のシナリオ)
このストラテジーは、ショート動画のリストやフィードなど、動画の切り替えが頻繁なシナリオに適しています:
// 1. 最大容量が 3 の再利用プールストラテジーを作成します。
ReusePoolLifecycleStrategy *strategy =
[[ReusePoolLifecycleStrategy alloc] initWithMaxPoolSize:3];
// 2. コントローラーの作成時にストラテジーを注入します。
AliPlayerController *controller =
[[AliPlayerController alloc] initWithLifecycleStrategy:strategy];
// 3. 通常どおりコントローラーを設定して使用します。
VideoSource *source = [VideoSource urlSourceWithUrl:@"https://example.com/video.mp4"];
AliPlayerModel *model = [[AliPlayerModel alloc] initWithVideoSource:source];
[controller configure:model];
[self.playerView attach:controller];AliPlayerController は initWithLifecycleStrategy: の呼び出し中に [strategy setupWithFactory:[AliPlayerKit playerFactory]] を自動的に呼び出して、デフォルトのファクトリをインジェクトします。ストラテジーを手動で初期化する必要はありません。
ID スコープストラテジー (プリロードのシナリオ)
この戦略は、複数の動画のプリロードや切り替えが必要なシナリオに適しています。同じ uniqueId は、常に同じインスタンスを返します。
// 1. 最大容量が 3 の ID スコープストラテジーを作成します。
IdScopedPoolLifecycleStrategy *strategy =
[[IdScopedPoolLifecycleStrategy alloc] initWithMaxPoolSize:3];
// 2. コントローラーの作成時にストラテジーを注入します。
AliPlayerController *controller =
[[AliPlayerController alloc] initWithLifecycleStrategy:strategy];
// 3. 使用方法 — configure は VideoSource.uniqueId を使用して内部的に ID をバインドします。
VideoSource *source = [VideoSource vidAuthSourceWithVid:@"your_video_id"
playAuth:@"your_play_auth"];
AliPlayerModel *model = [[AliPlayerModel alloc] initWithVideoSource:source];
[controller configure:model];
[self.playerView attach:controller];シングルトンストラテジー (リスト再生のシナリオ)
このストラテジーは、単一のグローバルインスタンスを使用します。すべてのコントローラーが同じプレーヤーを共有します:
// シングルトンストラテジーを取得します。dispatch_once により、グローバルで一意であることが保証されます。
SingletonLifecycleStrategy *strategy =
[SingletonLifecycleStrategy sharedInstance];
// コントローラーを作成します。
AliPlayerController *controller =
[[AliPlayerController alloc] initWithLifecycleStrategy:strategy];
// このストラテジーを使用するすべてのコントローラーが、同じプレーヤーインスタンスを共有します。
VideoSource *source = [VideoSource urlSourceWithUrl:@"https://example.com/video.mp4"];
AliPlayerModel *model = [[AliPlayerModel alloc] initWithVideoSource:source];
[controller configure:model];
[self.playerView attach:controller];シングルトンストラテジーを使用する場合、複数の AliPlayerController インスタンスが同時にプレーヤーを保持することはできません。これは状態の競合を引き起こします。SingletonLifecycleStrategy の init メソッドは NS_UNAVAILABLE としてマークされています。インスタンスは +sharedInstance を使用してのみ取得できます。
参考シナリオ:リスト再生
ScenePlaylistViewController には、SingletonLifecycleStrategy を使用して連続再生を実装する完全な例が示されています:
// プレーヤーのライフサイクルストラテジーを初期化します。
self.lifecycleStrategy = [SingletonLifecycleStrategy sharedInstance];
// コントローラーを作成し、ストラテジーを注入します。
self.currentController = [[AliPlayerController alloc]
initWithLifecycleStrategy:self.lifecycleStrategy];
// 再生完了の通知を登録し、次の動画の自動再生をトリガーします。
[self.currentController addNotificationDelegate:self];
// データを設定してコントローラーをアタッチします。アタッチ後に再生が自動的に開始されます。
AliPlayerModel *model = [[AliPlayerModel alloc] initWithVideoSource:videoSource];
[self.currentController configure:model];
[self.playerView attach:self.currentController];
// PlayerNotificationDelegate コールバック — 再生完了後に次の動画を自動再生します。
- (void)playerDidCompletion {
[self playNextVideo];
}リスト再生のシナリオでは、SingletonLifecycleStrategy がプレーヤーインスタンスを再利用します。これにより、頻繁な作成と破棄に伴うパフォーマンスのオーバーヘッドを回避できます。動画を切り替えるとき、configure: は recycle(old instance) + acquire(new instance) を自動的に実行します。プレーヤーのライフサイクルを手動で管理する必要はありません。
ストラテジーの詳細
DefaultLifecycleStrategy
これは最もシンプルなストラテジーです。ライフサイクルストラテジーを導入する前の従来の動作と同等です。
@interface DefaultLifecycleStrategy : BaseLifecycleStrategy <PlayerLifecycleStrategy>
@end特徴:
ステートレス。
acquirePlayerの呼び出しごとにファクトリを介して新しいインスタンスを作成します。recyclePlayer:force:の呼び出しごとに、forceの値にかかわらず、インスタンスを直接破棄します。メモリ使用量が最小です (使用後に解放されます)。
ほとんどの標準的な再生シナリオに適しています。
コアフロー:
操作 | 動作 |
| ファクトリを使用して新しいインスタンスを作成します |
|
|
| no-op (プールを維持しません) |
ReusePoolLifecycleStrategy
このストラテジーは、オブジェクトプールパターンに基づいています。アイドルプールとアクティブリストを維持します。
@interface ReusePoolLifecycleStrategy : BaseLifecycleStrategy <PlayerLifecycleStrategy>
/// プールの最大容量。デフォルトは 3 です。この容量を超えると、リサイクル時にインスタンスは直接破棄されます。
@property (nonatomic, assign) NSInteger maxPoolSize;
/// 現在プール内にあるアイドル状態のプレーヤー数。
@property (nonatomic, assign, readonly) NSInteger idleCount;
/// 取得済みで、まだリサイクルされていないアクティブなプレーヤー数。
@property (nonatomic, assign, readonly) NSInteger activeCount;
- (instancetype)initWithMaxPoolSize:(NSInteger)maxPoolSize NS_DESIGNATED_INITIALIZER;
@end特徴:
プレーヤーの初期化オーバーヘッドを抑えるため、まずアイドルプールからインスタンスを再利用します。
プールを事前に埋めるために
preloadWithCount:をサポートしています。プール容量は
maxPoolSizeによって制御されます。すべてのメソッドはスレッドセーフです。
ショート動画リストおよびフィードのシナリオに適しています。
コアフロー:
操作 | 動作 |
| まずアイドルプールからインスタンスを取得します。プールが空の場合は、ファクトリを使用して新しいインスタンスを作成します。 |
| 再生を停止し、インスタンスをアイドルプールに戻します。プールが満杯の場合は、インスタンスを破棄します。 |
| インスタンスを直ちに破棄します。 |
| アイドルプール内のすべてのインスタンスを破棄します。アクティブなインスタンスには影響しません。 |
| インスタンスを事前に作成し、アイドルプールに追加します。その数は |
IdScopedPoolLifecycleStrategy
このストラテジーは、uniqueId ごとに個別のプレーヤーインスタンスを維持します。同じ uniqueId は、常に同じインスタンスを返します。インスタンス数を制御するために、最近最も使用されていない (LRU) メカニズムを使用します。
@interface IdScopedPoolLifecycleStrategy : BaseLifecycleStrategy <PlayerLifecycleStrategy>
/// プールの最大容量。デフォルトは 3 です。上限を超えると、Least Recently Used (LRU) アルゴリズムにより、最も最近使用されていないインスタンスが自動的にエビクションされます。
/// この値を変更し、変更後の値が現在のインスタンス数より小さい場合、余剰インスタンスは LRU の順序で直ちにエビクションされます。
@property (nonatomic, assign) NSInteger maxPoolSize;
/// 現在のマッピングテーブル内にあるプレーヤーインスタンス数 (アクティブ、アイドルの両方)。
@property (nonatomic, assign, readonly) NSInteger poolCount;
- (instancetype)initWithMaxPoolSize:(NSInteger)maxPoolSize NS_DESIGNATED_INITIALIZER;
@end特徴:
ID バインディング。同じ
uniqueIdは常に同じインスタンスを再利用します。LRU のエビクションの仕組みにより、最も最近使用されていないインスタンスを自動的に削除します。
preloadWithCount:は、バインドされていないインスタンスの事前作成をサポートします。すべてのメソッドはスレッドセーフです。
この設計は、 Alibaba Cloud の短編ドラマソリューションにおけるマルチインスタンスのプレーヤープールの LRU 管理メカニズムに基づいています。
動画のプリロードおよびマルチ動画切り替えのシナリオに適しています。
コアフロー:
操作 | 動作 |
| 既存のインスタンスを返し、LRU の順序における位置を更新します。 |
| まずプリロード済みキューからインスタンスを取得します。キューが空の場合は、新しいインスタンスを作成して ID にバインドします。 |
| 再生のみを停止します。インスタンスはマッピングテーブルに残り、 LRU アルゴリズムにより自動的にエビクションされます。 |
| インスタンスをマッピングテーブルから削除し、直ちに破棄します。 |
| プリロード済みキューとマッピングテーブル内のインスタンスをクリアします。 |
| ID がバインドされていないインスタンスを作成します。これらは、新しい ID が初めて取得される際に使用されます。 |
ストラテジーが acquirePlayerWithUniqueId: メソッドを実装している場合、AliPlayerController は acquirePlayer の代わりにこのメソッドを呼び出します。これにより、VideoSource.uniqueId を介した ID バインディングが可能になります。同様に、recyclePlayer:uniqueId:force: は recyclePlayer:force: よりも優先して呼び出されます。
SingletonLifecycleStrategy
この戦略は、単一のグローバルなプレイヤーインスタンスを維持し、dispatch_once を使用して真のシングルトンパターンとして実装されています。
@interface SingletonLifecycleStrategy : BaseLifecycleStrategy <PlayerLifecycleStrategy>
/// グローバルで共有されるシングルトンストラテジーインスタンスを取得します。
+ (instancetype)sharedInstance;
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
@end特徴:
グローバルで一意です。このストラテジーを使用するすべてのコントローラーが、同じプレーヤーインスタンスを共有します。
メモリ使用量が最小です。
clearは空の操作であり、シングルトンインスタンスを破棄しません。インスタンスを明示的に破棄するには、recyclePlayer:force:YESを呼び出す必要があります。複数の動画を同時に再生するシナリオには適していません。
複数の
AliPlayerControllerインスタンスで同時にプレーヤーを保持することはできません。状態の競合が発生する原因となります。
コアフロー:
操作 | 動作 |
| グローバルインスタンスを返します。存在しない場合は、作成してから返します。 |
| 再生のみを停止します。インスタンスは保持されます。 |
| グローバルインスタンスを破棄します。 |
| no-op (シングルトンインスタンスは破棄されません)。 |
ストラテジー比較表
ストラテジー | 取得時の動作 | リサイクル時の動作 (force:NO) | シナリオ | TTFF (Time to First Frame) | スレッドセーフ |
Default | 毎回新規作成 | 直ちに破棄 | 通常再生 | 遅い | — |
ReusePool | プールから取得 / 新規作成 | プールに戻す / 満杯の場合は破棄 | ショート動画リスト | 速い | はい |
IdScoped | ID ヒット / プリロード済みを利用 / 新規作成 | マッピングテーブルに保持 / LRU によりエビクション | プリロード | 最速 | はい |
Singleton | 1 回だけ作成 | 再生のみ停止 | リスト再生 | 中 | — |
カスタム開発
ストラテジー プロトコル (PlayerLifecycleStrategy)
すべてのライフサイクルストラテジーは PlayerLifecycleStrategy プロトコルに準拠します。
@protocol PlayerLifecycleStrategy <NSObject>
@required
/// プレーヤーファクトリをインジェクトします。AliPlayerController が自動的に呼び出します。
- (void)setupWithFactory:(id<PlayerFactory>)factory;
/// プレーヤーインスタンスを取得します。ストラテジーが新規作成するか再利用するかを決定します。
- (id<MediaPlayer>)acquirePlayer;
/// プレーヤーインスタンスをリサイクルします。force:YES の場合は強制的に破棄します。force:NO の場合はストラテジーが決定します。
- (void)recyclePlayer:(nullable id<MediaPlayer>)player force:(BOOL)force;
/// ストラテジーが保持しているすべてのプレーヤーインスタンスを解放し、初期状態に戻します。
- (void)clear;
@optional
/// 指定された数のプレーヤーインスタンスをプールにプリロードします。
- (void)preloadWithCount:(NSInteger)count;
/// 一意のビジネス ID でプレーヤーインスタンスを取得します。IdScopedPoolLifecycleStrategy のみが実装します。
- (id<MediaPlayer>)acquirePlayerWithUniqueId:(NSString *)uniqueId;
/// 一意のビジネス ID でプレーヤーインスタンスをリサイクルします。IdScopedPoolLifecycleStrategy のみが実装します。
- (void)recyclePlayer:(nullable id<MediaPlayer>)player
uniqueId:(NSString *)uniqueId
force:(BOOL)force;
@endsetupWithFactory: は、AliPlayerController が initWithLifecycleStrategy: の呼び出し時に自動的に呼び出され、[AliPlayerKit playerFactory] が返すファクトリインスタンスをインジェクトします。開発者は通常、このメソッドを手動で呼び出す必要はありません。コントローラーを作成する前にインスタンスをプリロードするには、setupWithFactory: を手動で呼び出してから preloadWithCount: を呼び出すことができます。
ストラテジー 基底クラス (BaseLifecycleStrategy)
BaseLifecycleStrategy は、すべての組み込みストラテジーが共有する基底クラスです。ファクトリ管理とテンプレートメソッドを提供します。
@interface BaseLifecycleStrategy : NSObject
/// 現在インジェクトされているプレーヤーファクトリ (読み取り専用)。
@property (nonatomic, strong, readonly) id<PlayerFactory> factory;
/// プレーヤーファクトリをインジェクトします。この操作はべき等であり、最初の呼び出しでのみ有効です。以降の呼び出しは無視され、警告がログに記録されます。
- (void)setupWithFactory:(id<PlayerFactory>)factory;
/// ファクトリを使用して新しいプレーヤーインスタンスを作成します。子クラスはファクトリを直接呼び出すのではなく、このメソッドを呼び出す必要があります。
- (id<MediaPlayer>)createPlayer;
/// ファクトリを使用してプレーヤーインスタンスを破棄します。子クラスはファクトリを直接呼び出すのではなく、このメソッドを呼び出す必要があります。
- (void)destroyPlayer:(nullable id<MediaPlayer>)player;
@endBaseLifecycleStrategy 自体は PlayerLifecycleStrategy プロトコルへの準拠を宣言していません。子クラスは準拠を宣言し、acquirePlayer、recyclePlayer:force:、clear などのメソッドを実装する必要があります。子クラスは、factory を直接呼び出すのではなく、createPlayer および destroyPlayer: テンプレートメソッドを使用してプレーヤーインスタンスを操作する必要があります。これにより、操作が統一的にログに記録されます。
プレーヤーファクトリ (PlayerFactory)
PlayerFactory プロトコルは、プレーヤーインスタンスを作成および破棄するためのインターフェイスを定義します。
@protocol PlayerFactory <NSObject>
/// プレーヤーインスタンスを作成します。呼び出しごとに PlayerStateIdle 状態の新しいインスタンスを作成します。
- (id<MediaPlayer>)createPlayer;
/// プレーヤーインスタンスを破棄します。すべてのリソースを解放します。インスタンスが nil の場合、警告のみがログに記録されます。
- (void)destroyPlayer:(nullable id<MediaPlayer>)player;
@endフレームワークには組み込みの DefaultPlayerFactory が含まれており、Alibaba Cloud Player SDK (AliPlayer) を使用して標準インスタンスを作成します。 [AliPlayerKit setPlayerFactory:] を使用してカスタムファクトリに置き換えることができます。
カスタムストラテジーの例
以下の例は、ID マッピングに基づくシンプルなキャッシュポリシーを示しています。
@interface MyCacheLifecycleStrategy : BaseLifecycleStrategy <PlayerLifecycleStrategy>
@end
@implementation MyCacheLifecycleStrategy {
NSMutableDictionary<NSString *, id<MediaPlayer>> *_playerMap;
}
- (instancetype)init {
self = [super init];
if (self) {
_playerMap = [NSMutableDictionary dictionary];
}
return self;
}
#pragma mark - PlayerLifecycleStrategy
- (id<MediaPlayer>)acquirePlayer {
return [self createPlayer];
}
- (id<MediaPlayer>)acquirePlayerWithUniqueId:(NSString *)uniqueId {
id<MediaPlayer> player = _playerMap[uniqueId];
if (!player) {
player = [self createPlayer];
_playerMap[uniqueId] = player;
}
return player;
}
- (void)recyclePlayer:(id<MediaPlayer>)player
uniqueId:(NSString *)uniqueId
force:(BOOL)force {
if (!player) return;
if (force) {
[_playerMap removeObjectForKey:uniqueId];
[self destroyPlayer:player];
} else {
[player stop];
}
}
- (void)recyclePlayer:(id<MediaPlayer>)player force:(BOOL)force {
if (!player) return;
[self destroyPlayer:player];
}
- (void)clear {
for (id<MediaPlayer> player in _playerMap.allValues) {
[self destroyPlayer:player];
}
[_playerMap removeAllObjects];
}
@end登録と使用:
MyCacheLifecycleStrategy *strategy = [[MyCacheLifecycleStrategy alloc] init];
AliPlayerController *controller =
[[AliPlayerController alloc] initWithLifecycleStrategy:strategy];
// コントローラーは自動的に [strategy setupWithFactory:...] を呼び出してファクトリをインジェクトします。ライフサイクル フロー
コントローラーとストラテジー間のインタラクション フロー
AliPlayerController の初期化
↓
initWithLifecycleStrategy: → ストラテジー参照の保存
↓ → 自動的に [strategy setupWithFactory:[AliPlayerKit playerFactory]] を呼び出し
↓
[controller configure:model]
↓
├── プレーヤーの有無 → [strategy recyclePlayer:古いインスタンス force:NO]
↓
├── ストラテジーが acquirePlayerWithUniqueId: を実装しているか
│ ├── YES → [strategy acquirePlayerWithUniqueId:source.uniqueId]
│ └── NO → [strategy acquirePlayer]
↓
├── [player setDataSource:model]
├── [player prepare]
└── autoPlay ? → [player start]
↓
ビデオ切り替え → [controller configure:newModel]
↓ → recycle(古い) + acquire(新しい) + setDataSource + prepare
↓
[controller destroy]
↓
├── [strategy recyclePlayer:player force:YES]
└── コントローラーの解放ストラテジーリソースをクリーンアップするタイミング
タイミング | 操作 | 説明 |
ビデオ切り替え |
| 自動で処理されるため、手動操作は不要です。 |
コントローラーの破棄 |
| 自動完了 |
ページ離脱 |
| 手動で呼び出す必要があります。 |
プールリソースの解放 |
| 必要に応じて呼び出してください (例:メモリ警告時)。 |
ベストプラクティス
ストラテジー選択ガイド
シナリオ | 推奨されるストラテジー | 理由 |
通常の動画製品ページ | デフォルト | シンプルで直接的です。ページが破棄される際にリソースが解放されます。 |
ショート動画の縦スクロールリスト | ReusePool | インスタンスを再利用することで作成オーバーヘッドが削減され、スクロールの滑らかさが向上します。 |
動画のプリロード / 即時再生 | IdScoped | ID バインディングとプリロードにより、極めて高速な起動が可能になります。 |
連続リスト再生 | シングルトン | 単一のグローバルインスタンスにより、初期化の回数が削減されます。 |
ローエンドデバイス / 低メモリ | シングルトン | 単一のグローバルインスタンスにより、最小限のメモリフットプリントを実現します。 |
ポッドキャスト / 音声再生 | シングルトン | 単一の音声ストリームシナリオでは、複数のインスタンスは不要です。 |
メモリ管理の推奨事項
推奨事項 | 説明 |
メモリ警告をリッスンする | プールベースのストラテジーは |
適切なプール容量を設定する | 各プレーヤーインスタンスは約 35 MB から 40 MB のメモリを使用します。デバイスのパフォーマンスに基づいて |
バックグラウンドでアイドルプールを解放する | アプリがバックグラウンドに入った際に、 |
ページ破棄時に destroy を呼び出す |
|
// メモリ警告をリッスンして、プールリソースを解放します。
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(handleMemoryWarning:)
name:UIApplicationDidReceiveMemoryWarningNotification
object:nil];
- (void)handleMemoryWarning:(NSNotification *)notification {
[self.lifecycleStrategy clear];
}ページライフサイクル管理
@interface MyViewController ()
@property (nonatomic, strong) AliPlayerView *playerView;
@property (nonatomic, strong) AliPlayerController *controller;
@property (nonatomic, strong) id<PlayerLifecycleStrategy> lifecycleStrategy;
@end
@implementation MyViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.lifecycleStrategy = [[ReusePoolLifecycleStrategy alloc] initWithMaxPoolSize:3];
self.controller = [[AliPlayerController alloc]
initWithLifecycleStrategy:self.lifecycleStrategy];
// ... configure + attach
}
- (void)dealloc {
// 必須: コントローラーを破棄します。
if (_controller) {
[_controller destroy];
}
// オプション: このページがストラテジーの最後のユーザーである場合、プールリソースを解放します。
if (_lifecycleStrategy) {
[_lifecycleStrategy clear];
}
}
@end注意事項
シナリオ | 推奨される方法 | 理由 |
ページの破棄 |
| メモリリークを回避するため |
ストラテジーのクリーンアップ | 最後のユーザーが | プール内のアイドルインスタンスを解放するため |
シングルトンストラテジー | 複数のコントローラーで同時にプレーヤーを保持しないこと | 状態の競合を回避するため |
ファクトリインジェクション |
| コントローラーが自動的にインジェクトします。メソッドはべき等です (最初の呼び出しのみ有効)。 |
プリロード | コントローラー作成後に呼び出す | コントローラー作成時にファクトリが自動的にインジェクトされるため。 |
よくある間違い
// ✗ 誤り: dealloc でコントローラーの破棄を忘れる。
- (void)dealloc {
[self.playerView detach];
// [_controller destroy] が呼び出されず、メモリリークが発生します。
}
// ✓ 正しい: コントローラーを破棄し、必要に応じてストラテジーをクリーンアップします。
- (void)dealloc {
if (_controller) {
[_controller destroy];
}
if (_lifecycleStrategy) {
[_lifecycleStrategy clear];
}
}// ✗ 誤り: シングルトンストラテジーで複数のコントローラーを同時に保持する。
SingletonLifecycleStrategy *strategy = [SingletonLifecycleStrategy sharedInstance];
AliPlayerController *controller1 = [[AliPlayerController alloc] initWithLifecycleStrategy:strategy];
AliPlayerController *controller2 = [[AliPlayerController alloc] initWithLifecycleStrategy:strategy];
// controller1 と controller2 が同じプレーヤーインスタンスを共有し、状態の競合が発生します。
// ✓ 正しい: 一度に 1 つのコントローラーのみがシングルトンストラテジーを使用するようにします。
[controller1 destroy];
AliPlayerController *controller2 = [[AliPlayerController alloc] initWithLifecycleStrategy:strategy];// ✗ 誤り: SingletonLifecycleStrategy を alloc init しようとする。
SingletonLifecycleStrategy *strategy = [[SingletonLifecycleStrategy alloc] init]; // コンパイルエラー。
// ✓ 正しい: sharedInstance を通じてインスタンスを取得します。
SingletonLifecycleStrategy *strategy = [SingletonLifecycleStrategy sharedInstance];API リファレンス
コアクラスとプロトコル
プロトコル / クラス | 説明 |
| ライフサイクル ストラテジー プロトコル。インスタンスの取得、リサイクル、クリアのためのインターフェイスを定義します。 |
| ストラテジー 基底クラス。ファクトリ管理と createPlayer/destroyPlayer: テンプレートメソッドを提供します。 |
| プレーヤー ファクトリ プロトコル。インスタンスの作成と破棄のためのインターフェイスを定義します。 |
| デフォルト ファクトリ実装。Alibaba Cloud Player SDK を使用してインスタンスを作成します。 |
| メディア プレーヤー プロトコル。再生コントロール、ステータス クエリなどのインターフェイスを定義します。 |
組み込みストラテジー
クラス | 作成メソッド | 主要なプロパティ |
|
| — |
|
|
|
|
|
|
|
| — |
PlayerLifecycleStrategy メソッド
メソッド | 必須 | 説明 |
| はい | プレーヤー ファクトリを注入します。コントローラーによって自動的に呼び出されます。 |
| はい | プレーヤー インスタンスを取得します。 |
| はい | プレーヤー インスタンスをリサイクルします。 |
| はい | キャッシュされたすべてのインスタンスを解放します。 |
| いいえ | インスタンスをプリロードします。ReusePool と IdScoped によって実装されます。 |
| いいえ | uniqueId によってインスタンスを取得します。IdScoped によって実装されます。 |
| いいえ | uniqueId によってインスタンスをリサイクルします。IdScoped によって実装されます。 |
BaseLifecycleStrategy メソッド
メソッド / プロパティ | 説明 |
| 現在注入されているプレーヤー ファクトリ (読み取り専用)。 |
| ファクトリを注入します。べき等で、最初の呼び出しのみ有効です。 |
| ファクトリを通じて統一されたロギングでインスタンスを作成します。 |
| ファクトリを通じて統一されたロギングでインスタンスを破棄します。 |
force パラメーターの説明
force の値 | 動作 | シナリオ |
| ストラテジーがインスタンスをプールに戻すか、再生を停止するだけかを決定します。 | 通常のビデオ切り替え。 |
| ストラテジーに関係なく、インスタンスを即座に破棄します。 | コントローラーの破棄。 |
uniqueId の説明
uniqueId は VideoSource の一意のビジネス識別子プロパティであり、異なる動画ソースを区別するために使用されます。ストラテジーによって使用方法が異なります。
ストラテジー | uniqueId の用途 |
デフォルト | 使用されません |
ReusePool | 使用されません |
IdScoped | コア識別子。同じ uniqueId は常に同じインスタンスを返します。 |
シングルトン | 使用されません |
使用例
PlayerKitUsages/UsageLifecycleStrategy モジュールは、プレーヤーのライフサイクルストラテジーの使用方法に関する完全な例を提供します。このモジュールは、4つの組み込みストラテジー (Default、ReusePool、Singleton、IdScopedPool) 間の切り替え、マルチソース再生でのインスタンスの再利用動作 (NEW/REUSED/HIT)、およびストラテジーとコントローラーのリソース クリーンアップ フローを示します。