A estratégia de ciclo de vida do player é um design arquitetônico central no AliPlayerKit. Ela unifica o gerenciamento de criação, reutilização, reciclagem e destruição de instâncias do player. Isso permite um agendamento de recursos mais eficiente e a otimização de desempenho em diferentes cenários de negócios.
Introdução
O que é uma estratégia de ciclo de vida do player?
Uma estratégia de ciclo de vida do player é um mecanismo arquitetônico que gerencia o ciclo de vida das instâncias do player. Ela define operações centrais, como aquisição, reciclagem e limpeza de instâncias do player. Isso desacopla o gerenciamento de recursos do player da sua lógica de negócios.
Diferentes cenários de negócios possuem requisitos distintos para o gerenciamento de instâncias do player:
|
Cenário |
Requisitos |
Estratégia recomendada |
|
Reprodução de vídeo normal |
Simples e direto, sem necessidade de reutilização |
Default |
|
Lista de vídeos curtos |
Troca frequente, requer inicialização rápida |
ReusePool |
|
Pré-carregamento de vídeo |
Vincula um ID a uma instância, suporta pré-carregamento |
IdScopedPool |
|
Cenários sensíveis a memória |
Instância global única, ocupação mínima de memória |
Singleton |
Valor principal
Gerenciar o ciclo de vida do player com um padrão de estratégia oferece as seguintes vantagens centrais:
Desacoplamento: Sua lógica de negócios não precisa lidar com os detalhes de criação e destruição de instâncias do player.
Flexibilidade: escolha diferentes estratégias em tempo de execução sem alterar sua lógica de negócios.
Extensibilidade: implemente políticas personalizadas para atender a necessidades específicas de negócios.
Observabilidade: o gerenciamento unificado do ciclo de vida permite que você visualize o status e simplifica a depuração.
Contexto do design
A Estratégia de Ciclo de Vida do Player teve origem no pool de players de múltiplas instâncias na solução de minisséries do Alibaba Cloud. O design atende a requisitos rigorosos de tempo até o primeiro quadro (TTFF), troca fluida e controle de memória em feeds de rolagem rápida. O AliPlayerKit abstrai essa prática em um padrão de estratégia para criar uma arquitetura mais geral e flexível no gerenciamento do ciclo de vida do player.
Recursos
Capacidades principais
|
Capacidade |
Descrição |
|
Aquisição de instância |
|
|
Reciclagem de instância |
|
|
Limpeza de recursos |
|
|
Pré-carregamento |
|
|
Vinculação de ID |
|
|
Injeção de factory |
|
Estratégias integradas
O AliPlayerKit fornece quatro estratégias integradas de ciclo de vida do player:
|
Estratégia |
Nome da classe |
Descrição |
Cenários |
|
Estratégia padrão |
|
Crie uma nova instância a cada vez. Destrói a instância imediatamente após o uso. |
Reprodução normal |
|
Estratégia de pool de reutilização |
|
Mantém um pool ocioso. Reutiliza instâncias do pool primeiro. |
Lista de vídeos curtos |
|
Política de vinculação de ID |
|
Mantém uma instância separada para cada uniqueId. Evita instâncias usando um algoritmo LRU (Least Recently Used). |
Pré-carregamento de vídeo |
|
Estratégia singleton |
|
Uma única instância global. Todas as solicitações de aquisição retornam a mesma instância. |
Reprodução em lista, cenários sensíveis a memória |
Camadas de arquitetura
┌──────────────────────────────────────────────────────────────┐
│ AliPlayerController │
│ initWithLifecycleStrategy: Injects strategy │
│ configure: Internally calls recycle(old) + acquire(new) │
│ destroy: Internally calls recycle(player, force:YES) │
├──────────────────────────────────────────────────────────────┤
│ PlayerLifecycleStrategy protocol │
│ setupWithFactory: / acquirePlayer / recyclePlayer:force: │
│ clear / preloadWithCount: / acquirePlayerWithUniqueId: │
├──────────────────────────────────────────────────────────────┤
│ BaseLifecycleStrategy base class │
│ factory / createPlayer / destroyPlayer: │
├──────────┬──────────┬─────────────────┬──────────────────────┤
│ Default │ReusePool │ IdScopedPool │ Singleton │
│ New each time │ Pool reuse │ ID binding + LRU │ Global singleton │
└──────────┴──────────┴─────────────────┴──────────────────────┘
│ │
│ PlayerFactory protocol / DefaultPlayerFactory │
│ createPlayer / destroyPlayer: │
└──────────────────────────────────────────────────────────────┘
Uso
Uso básico — Estratégia Default
Esta é a maneira mais simples de usar o player. Nenhuma configuração extra é necessária. O AliPlayerController usa o DefaultLifecycleStrategy por padrão:
// Create a controller. The default strategy is used automatically.
AliPlayerController *controller = [[AliPlayerController alloc] init];
// Create the playback data.
VideoSource *source = [VideoSource urlSourceWithUrl:@"https://example.com/video.mp4"];
AliPlayerModel *model = [[AliPlayerModel alloc] initWithVideoSource:source];
// Configure the controller and attach it to the player view.
[controller configure:model];
[self.playerView attach:controller];
Comportamento da estratégia Default: uma nova instância é criada para cada chamada de acquirePlayer. A instância é destruída imediatamente a cada chamada de recyclePlayer:force:. Nenhum pool é mantido.
Estratégia de pool de reutilização (cenário de vídeos curtos)
Essa estratégia é ideal para cenários com troca frequente de vídeos, como listas e feeds de vídeos curtos:
// 1. Create a reuse pool strategy with a maximum capacity of 3.
ReusePoolLifecycleStrategy *strategy =
[[ReusePoolLifecycleStrategy alloc] initWithMaxPoolSize:3];
// 2. Inject the strategy when creating the controller.
AliPlayerController *controller =
[[AliPlayerController alloc] initWithLifecycleStrategy:strategy];
// 3. Configure and use the controller as normal.
VideoSource *source = [VideoSource urlSourceWithUrl:@"https://example.com/video.mp4"];
AliPlayerModel *model = [[AliPlayerModel alloc] initWithVideoSource:source];
[controller configure:model];
[self.playerView attach:controller];
O AliPlayerController chama automaticamente [strategy setupWithFactory:[AliPlayerKit playerFactory]] para injetar a factory padrão durante a chamada initWithLifecycleStrategy:. Você não precisa inicializar a estratégia manualmente.
Estratégia com escopo de ID (cenário de pré-carregamento)
Essa estratégia é adequada para cenários que exigem pré-carregamento e troca entre vários vídeos. O mesmo uniqueId sempre retorna a mesma instância:
// 1. Create an ID-scoped strategy with a maximum capacity of 3.
IdScopedPoolLifecycleStrategy *strategy =
[[IdScopedPoolLifecycleStrategy alloc] initWithMaxPoolSize:3];
// 2. Inject the strategy when creating the controller.
AliPlayerController *controller =
[[AliPlayerController alloc] initWithLifecycleStrategy:strategy];
// 3. Usage — configure internally binds the ID using VideoSource.uniqueId.
VideoSource *source = [VideoSource vidAuthSourceWithVid:@"your_video_id"
playAuth:@"your_play_auth"];
AliPlayerModel *model = [[AliPlayerModel alloc] initWithVideoSource:source];
[controller configure:model];
[self.playerView attach:controller];
Estratégia Singleton (cenário de reprodução em lista)
Essa estratégia usa uma única instância global. Todos os controladores compartilham o mesmo player:
// Get the singleton strategy. dispatch_once ensures it is globally unique.
SingletonLifecycleStrategy *strategy =
[SingletonLifecycleStrategy sharedInstance];
// Create the controller.
AliPlayerController *controller =
[[AliPlayerController alloc] initWithLifecycleStrategy:strategy];
// All controllers that use this strategy share the same player instance.
VideoSource *source = [VideoSource urlSourceWithUrl:@"https://example.com/video.mp4"];
AliPlayerModel *model = [[AliPlayerModel alloc] initWithVideoSource:source];
[controller configure:model];
[self.playerView attach:controller];
Ao usar a estratégia singleton, múltiplas instâncias de AliPlayerController não podem reter o player ao mesmo tempo. Isso causaria conflitos de estado. O método init do SingletonLifecycleStrategy é marcado como NS_UNAVAILABLE. Você só pode obter a instância através de +sharedInstance.
Referência de cenário: Reprodução em lista
O ScenePlaylistViewController mostra um exemplo completo de uso do SingletonLifecycleStrategy para implementar reprodução contínua:
// Initialize the player lifecycle strategy.
self.lifecycleStrategy = [SingletonLifecycleStrategy sharedInstance];
// Create the controller and inject the strategy.
self.currentController = [[AliPlayerController alloc]
initWithLifecycleStrategy:self.lifecycleStrategy];
// Register a notification for playback completion to trigger autoplay for the next video.
[self.currentController addNotificationDelegate:self];
// Configure the data and attach the controller. Playback starts automatically after attachment.
AliPlayerModel *model = [[AliPlayerModel alloc] initWithVideoSource:videoSource];
[self.currentController configure:model];
[self.playerView attach:self.currentController];
// PlayerNotificationDelegate callback — Autoplay the next video after playback completes.
- (void)playerDidCompletion {
[self playNextVideo];
}
Em um cenário de reprodução em lista, o SingletonLifecycleStrategy reutiliza a instância do player. Isso evita a sobrecarga de desempenho de criações e destruições frequentes. Ao trocar de vídeo, o configure: executa automaticamente recycle(old instance) + acquire(new instance). Não gerencie o ciclo de vida do player manualmente.
Detalhes da estratégia
DefaultLifecycleStrategy
Esta é a estratégia mais simples. Equivale ao comportamento original antes da introdução das estratégias de ciclo de vida.
@interface DefaultLifecycleStrategy : BaseLifecycleStrategy <PlayerLifecycleStrategy>
@end
Recursos:
Sem estado. Crie uma nova instância através da factory para cada chamada de
acquirePlayer.Destrói a instância diretamente a cada chamada de
recyclePlayer:force:, independentemente do valor deforce.Menor uso de memória (liberada após o uso).
Ideal para a maioria dos cenários de reprodução padrão.
Fluxo principal:
|
Operação |
Comportamento |
|
|
Crie uma nova instância através da factory |
|
|
Destrói a instância diretamente, independentemente do valor de |
|
|
Nenhuma operação (não mantém um pool) |
ReusePoolLifecycleStrategy
Essa estratégia baseia-se no padrão de pool de objetos. Ela mantém um pool ocioso e uma lista ativa.
@interface ReusePoolLifecycleStrategy : BaseLifecycleStrategy <PlayerLifecycleStrategy>
/// The maximum capacity of the pool. Default is 3. If this capacity is exceeded, recycle will destroy the instance directly.
@property (nonatomic, assign) NSInteger maxPoolSize;
/// The number of idle players currently in the pool.
@property (nonatomic, assign, readonly) NSInteger idleCount;
/// The number of active players that have been acquired but not yet recycled.
@property (nonatomic, assign, readonly) NSInteger activeCount;
- (instancetype)initWithMaxPoolSize:(NSInteger)maxPoolSize NS_DESIGNATED_INITIALIZER;
@end
Recursos:
Reutiliza instâncias do pool ocioso primeiro para reduzir a sobrecarga de inicialização do player.
Suporta
preloadWithCount:para pré-preencher o pool.A capacidade do pool é controlada por
maxPoolSize.Todos os métodos são thread-safe.
Adequada para listas de vídeos curtos e cenários de feed.
Fluxo principal:
|
Operação |
Comportamento |
|
|
Obtém uma instância do pool ocioso primeiro. Se o pool estiver vazio, cria uma nova instância através da factory. |
|
|
Interrompe a reprodução e retorna a instância ao pool ocioso. Se o pool estiver cheio, destrói a instância. |
|
|
Destrói a instância imediatamente. |
|
|
Destrói todas as instâncias no pool ocioso. As instâncias ativas não são afetadas. |
|
|
Pré-cria instâncias e as adiciona ao pool ocioso. O número é limitado por |
IdScopedPoolLifecycleStrategy
Essa estratégia mantém uma instância de player separada para cada uniqueId. O mesmo uniqueId sempre retorna a mesma instância. Ela usa um mecanismo LRU (Least Recently Used) para controlar o número de instâncias.
@interface IdScopedPoolLifecycleStrategy : BaseLifecycleStrategy <PlayerLifecycleStrategy>
/// The maximum capacity of the pool. Default is 3. When exceeded, the least recently used instance is automatically evicted by the LRU algorithm.
/// If you change this value and the new value is less than the current number of instances, excess instances are immediately evicted in LRU order.
@property (nonatomic, assign) NSInteger maxPoolSize;
/// The number of player instances in the current mapping table (both active and idle).
@property (nonatomic, assign, readonly) NSInteger poolCount;
- (instancetype)initWithMaxPoolSize:(NSInteger)maxPoolSize NS_DESIGNATED_INITIALIZER;
@end
Recursos:
Vinculação de ID. O mesmo
uniqueIdsempre reutiliza a mesma instância.O mecanismo de evicção LRU limpa automaticamente as instâncias menos recentemente usadas.
Suporta
preloadWithCount:para pré-criar instâncias não vinculadas.Todos os métodos são thread-safe.
O design baseia-se no mecanismo de gerenciamento LRU do pool de players de múltiplas instâncias na solução de minisséries do Alibaba Cloud.
Adequada para cenários de pré-carregamento de vídeo e troca de múltiplos vídeos.
Fluxo principal:
|
Operação |
Comportamento |
|
|
Retorna a instância existente e atualiza sua posição na ordem LRU. |
|
|
Obtém uma instância da fila pré-carregada primeiro. Caso contrário, cria uma nova instância e a vincula ao ID. |
|
|
Apenas interrompe a reprodução. A instância permanece na tabela de mapeamento e é evictada automaticamente pelo algoritmo LRU. |
|
|
Remove a instância da tabela de mapeamento e a destrói imediatamente. |
|
|
Limpa as instâncias na fila pré-carregada e na tabela de mapeamento. |
|
|
Cria instâncias sem um ID vinculado. Elas são usadas na primeira vez que um novo ID é adquirido. |
Se uma estratégia implementar o método acquirePlayerWithUniqueId:, o AliPlayerController o chamará em vez de acquirePlayer. Isso permite a vinculação de ID através de VideoSource.uniqueId. Da mesma forma, recyclePlayer:uniqueId:force: é chamado preferencialmente no lugar de recyclePlayer:force:.
SingletonLifecycleStrategy
Essa estratégia mantém uma única instância global do player. É implementada como um verdadeiro padrão singleton usando dispatch_once.
@interface SingletonLifecycleStrategy : BaseLifecycleStrategy <PlayerLifecycleStrategy>
/// Gets the globally shared singleton strategy instance.
+ (instancetype)sharedInstance;
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
@end
Recursos:
Globalmente única. Todos os controladores que usam essa estratégia compartilham a mesma instância do player.
Menor uso de memória.
clearé uma operação nula (no-op). Não destrói a instância singleton. Você deve destruí-la explicitamente chamandorecyclePlayer:force:YES.Não recomendada para cenários em que vários vídeos são reproduzidos ao mesmo tempo.
Múltiplas instâncias de
AliPlayerControllernão podem reter o player ao mesmo tempo. Isso causaria conflitos de estado.
Fluxo principal:
|
Operação |
Comportamento |
|
|
Retorna a instância global se ela existir. Caso contrário, a cria. |
|
|
Apenas interrompe a reprodução. A instância é retida. |
|
|
Destrói a instância global. |
|
|
Operação nula (não destrói a instância singleton). |
Tabela de comparação de estratégias
|
Estratégia |
Comportamento de aquisição |
Comportamento de reciclagem (force:NO) |
Cenários |
TTFF |
Thread safety |
|
Default |
Cada novo item |
Destrói imediatamente |
Reprodução normal |
Lento |
— |
|
ReusePool |
Obter do pool / Criar novo |
Retornar ao pool / Destrói se cheio |
Lista de vídeos curtos |
Rápido |
Sim |
|
IdScoped |
ID hit / Pré-preenchido / Criar novo |
Manter na tabela de mapeamento / Evicção por LRU |
Pré-carregamento |
Mais rápido |
Sim |
|
Singleton |
Crie apenas uma vez |
Apenas interrompe a reprodução |
Reprodução em lista |
Médio |
— |
Desenvolvimento personalizado
Protocolo de estratégia (PlayerLifecycleStrategy)
Todas as estratégias de ciclo de vida estão em conformidade com o protocolo PlayerLifecycleStrategy:
@protocol PlayerLifecycleStrategy <NSObject>
@required
/// Injects the player factory. Called automatically by AliPlayerController.
- (void)setupWithFactory:(id<PlayerFactory>)factory;
/// Gets a player instance. The strategy decides whether to create or reuse one.
- (id<MediaPlayer>)acquirePlayer;
/// Recycles a player instance. force:YES forces destruction. force:NO lets the strategy decide.
- (void)recyclePlayer:(nullable id<MediaPlayer>)player force:(BOOL)force;
/// Releases all player instances held by the strategy and restores the initial state.
- (void)clear;
@optional
/// Preloads a specified number of player instances into the pool.
- (void)preloadWithCount:(NSInteger)count;
/// Gets a player instance by a unique business ID. Implemented only by IdScopedPoolLifecycleStrategy.
- (id<MediaPlayer>)acquirePlayerWithUniqueId:(NSString *)uniqueId;
/// Recycles a player instance by a unique business ID. Implemented only by IdScopedPoolLifecycleStrategy.
- (void)recyclePlayer:(nullable id<MediaPlayer>)player
uniqueId:(NSString *)uniqueId
force:(BOOL)force;
@end
O AliPlayerController chama setupWithFactory: automaticamente durante a chamada initWithLifecycleStrategy: para injetar a instância da factory retornada por [AliPlayerKit playerFactory]. Os desenvolvedores geralmente não precisam chamar esse método manualmente. Para pré-carregar instâncias antes de criar um controlador, você pode chamar manualmente setupWithFactory: e, em seguida, preloadWithCount:.
Classe base da estratégia (BaseLifecycleStrategy)
O BaseLifecycleStrategy é a classe base compartilhada para todas as estratégias integradas. Ele fornece gerenciamento de factory e métodos de modelo (template methods):
@interface BaseLifecycleStrategy : NSObject
/// The currently injected player factory (read-only).
@property (nonatomic, strong, readonly) id<PlayerFactory> factory;
/// Injects the player factory. This is idempotent. It only takes effect on the first call. Subsequent calls are ignored and a warning is logged.
- (void)setupWithFactory:(id<PlayerFactory>)factory;
/// Creates a new player instance through the factory. Child classes should call this method instead of calling the factory directly.
- (id<MediaPlayer>)createPlayer;
/// Destroys a player instance through the factory. Child classes should call this method instead of calling the factory directly.
- (void)destroyPlayer:(nullable id<MediaPlayer>)player;
@end
O próprio BaseLifecycleStrategy não declara conformidade com o protocolo PlayerLifecycleStrategy. As classes filhas devem declarar conformidade e implementar métodos como acquirePlayer, recyclePlayer:force: e clear. As classes filhas devem usar os métodos de modelo createPlayer e destroyPlayer: para operar nas instâncias do player em vez de chamar a factory diretamente. Isso garante que as operações sejam registradas em log de forma uniforme.
Factory do player (PlayerFactory)
O protocolo PlayerFactory define a interface para criação e destruição de instâncias do player:
@protocol PlayerFactory <NSObject>
/// Creates a player instance. Each call creates a new instance in the PlayerStateIdle state.
- (id<MediaPlayer>)createPlayer;
/// Destroys a player instance. This releases all resources. If the instance is nil, only a warning is logged.
- (void)destroyPlayer:(nullable id<MediaPlayer>)player;
@end
O framework inclui o DefaultPlayerFactory integrado, que usa o Alibaba Cloud Player SDK (AliPlayer) para criar instâncias padrão. Você pode substituí-lo por uma factory personalizada usando [AliPlayerKit setPlayerFactory:].
Exemplo de estratégia personalizada
O exemplo a seguir mostra uma política de cache simples baseada em mapeamento de 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
Registro e uso:
MyCacheLifecycleStrategy *strategy = [[MyCacheLifecycleStrategy alloc] init];
AliPlayerController *controller =
[[AliPlayerController alloc] initWithLifecycleStrategy:strategy];
// The controller automatically calls [strategy setupWithFactory:...] to inject the factory.
Fluxo do ciclo de vida
Fluxo de interação entre controlador e estratégia
AliPlayerController initialization
↓
initWithLifecycleStrategy: → Saves strategy reference
↓ → Automatically calls [strategy setupWithFactory:[AliPlayerKit playerFactory]]
↓
[controller configure:model]
↓
├── Has player? → [strategy recyclePlayer:old instance force:NO]
↓
├── Does strategy implement acquirePlayerWithUniqueId:?
│ ├── YES → [strategy acquirePlayerWithUniqueId:source.uniqueId]
│ └── NO → [strategy acquirePlayer]
↓
├── [player setDataSource:model]
├── [player prepare]
└── autoPlay ? → [player start]
↓
Switch video source → [controller configure:newModel]
↓ → recycle(old) + acquire(new) + setDataSource + prepare
↓
[controller destroy]
↓
├── [strategy recyclePlayer:player force:YES]
└── Controller release
Quando limpar os recursos da estratégia
|
Momento |
Operação |
Descrição |
|
Troca de vídeo |
|
Automático, nenhuma operação manual necessária |
|
Destruição do controlador |
O método |
Autocompletar |
|
Saída da página |
Chame |
Deve ser chamado manualmente |
|
Liberação de recursos do pool |
|
Chame conforme necessário (por exemplo, em um aviso de memória) |
Melhores práticas
Guia de seleção de estratégia
|
Cenário |
Estratégia recomendada |
Motivo |
|
Página de product de vídeo normal |
Default |
Simples e direto. Os recursos são liberados quando a página é destruída. |
|
Lista de rolagem vertical de vídeos curtos |
ReusePool |
A reutilização de instâncias reduz a sobrecarga de criação e melhora a fluidez da rolagem. |
|
Pré-carregamento de vídeo / Reprodução instantânea |
IdScoped |
A vinculação de ID e o pré-carregamento permitem uma inicialização extremamente rápida. |
|
Reprodução contínua em lista |
Singleton |
Uma única instância global reduz o número de inicializações. |
|
Dispositivos de baixo custo / Pouca memória |
Singleton |
Instância global única para ocupação mínima de memória. |
|
Podcast / Reprodução de áudio |
Singleton |
Um cenário de fluxo de áudio único não requer múltiplas instâncias. |
Recomendações de gerenciamento de memória
|
Recomendação |
Descrição |
|
Ouça os avisos de memória |
Estratégias baseadas em pool devem ouvir |
|
Defina uma capacidade de pool razoável |
Cada instância do player usa cerca de 35 MB a 40 MB de memória. Defina |
|
Libere o pool ocioso em segundo plano |
Chame |
|
Chame destroy quando a página for destruída |
Você deve chamar |
// Listen for memory warnings to release pool resources.
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(handleMemoryWarning:)
name:UIApplicationDidReceiveMemoryWarningNotification
object:nil];
- (void)handleMemoryWarning:(NSNotification *)notification {
[self.lifecycleStrategy clear];
}
Gerenciamento do ciclo de vida da página
@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 {
// Required: Destroy the controller.
if (_controller) {
[_controller destroy];
}
// Optional: If this page is the last user of the strategy, release the pool resources.
if (_lifecycleStrategy) {
[_lifecycleStrategy clear];
}
}
@end
Observações
|
Cenário |
Prática recomendada |
Motivo |
|
Destruição da página |
Chame |
Evita vazamentos de memória |
|
Limpeza da estratégia |
O último usuário chama |
Libera instâncias ociosas no pool |
|
Estratégia Singleton |
Não permita que múltiplos controladores retenham o player ao mesmo tempo |
Evita conflitos de estado |
|
Injeção de factory |
Não chame |
O controlador a injeta automaticamente, e o método é idempotente (apenas a primeira chamada é efetiva). |
|
Pré-carregamento |
Chame após a criação do controlador |
A factory é injetada automaticamente quando o controlador é criado. |
Erros comuns
// ✗ Incorrect: Forgetting to destroy the controller in dealloc.
- (void)dealloc {
[self.playerView detach];
// [_controller destroy] is not called, causing a memory leak.
}
// ✓ Correct: Destroy the controller and clean up the strategy as needed.
- (void)dealloc {
if (_controller) {
[_controller destroy];
}
if (_lifecycleStrategy) {
[_lifecycleStrategy clear];
}
}
// ✗ Incorrect: Holding multiple controllers at the same time with a singleton strategy.
SingletonLifecycleStrategy *strategy = [SingletonLifecycleStrategy sharedInstance];
AliPlayerController *controller1 = [[AliPlayerController alloc] initWithLifecycleStrategy:strategy];
AliPlayerController *controller2 = [[AliPlayerController alloc] initWithLifecycleStrategy:strategy];
// controller1 and controller2 share the same player instance, causing a state conflict.
// ✓ Correct: Ensure only one controller uses the singleton strategy at a time.
[controller1 destroy];
AliPlayerController *controller2 = [[AliPlayerController alloc] initWithLifecycleStrategy:strategy];
// ✗ Incorrect: Trying to alloc init SingletonLifecycleStrategy.
SingletonLifecycleStrategy *strategy = [[SingletonLifecycleStrategy alloc] init]; // Compile error.
// ✓ Correct: Get the instance through sharedInstance.
SingletonLifecycleStrategy *strategy = [SingletonLifecycleStrategy sharedInstance];
Referência da API
Classes e protocolos principais
|
Protocolo / Classe |
Descrição |
|
|
Protocolo de estratégia de ciclo de vida. Define interfaces para aquisição, reciclagem e limpeza de instâncias. |
|
|
Classe base da estratégia. Fornece gerenciamento de factory e métodos de modelo createPlayer/destroyPlayer:. |
|
|
Protocolo da factory do player. Define interfaces para criação e destruição de instâncias. |
|
|
Implementação da factory padrão. Usa o Alibaba Cloud Player SDK para criar instâncias. |
|
|
Protocolo do media player. Define interfaces para controle de reprodução, consultas de status e muito mais. |
Estratégias integradas
|
Classe |
Método de criação |
Propriedades principais |
|
|
|
— |
|
|
|
|
|
|
|
|
|
|
|
— |
Métodos do PlayerLifecycleStrategy
|
Método |
Obrigatório |
Descrição |
|
|
Sim |
Injeta a factory do player. Chamado automaticamente pelo controlador. |
|
|
Sim |
Obtém uma instância do player. |
|
|
Sim |
Recicla uma instância do player. |
|
|
Sim |
Libera todas as instâncias em cache. |
|
|
Não |
Pré-carrega instâncias. Implementado por ReusePool e IdScoped. |
|
|
Não |
Obtém uma instância por uniqueId. Implementado por IdScoped. |
|
|
Não |
Recicla uma instância por uniqueId. Implementado por IdScoped. |
Métodos do BaseLifecycleStrategy
|
Método/Propriedade |
Descrição |
|
|
A factory do player atualmente injetada (somente leitura). |
|
|
Injeta a factory. Idempotente, apenas a primeira chamada é efetiva. |
|
|
Cria uma instância através da factory com registro em log uniforme. |
|
|
Destrói uma instância através da factory com registro em log uniforme. |
Descrição do parâmetro force
|
Valor de force |
Comportamento |
Cenário |
|
|
A estratégia decide se retorna a instância ao pool ou apenas interrompe a reprodução. |
Troca normal de vídeo. Usado dentro de |
|
|
Destrói a instância imediatamente, independentemente da estratégia. |
Destruição do controlador. Usado dentro de |
Descrição do uniqueId
O uniqueId é uma propriedade de ID de negócios exclusiva em VideoSource usada para distinguir diferentes source de vídeo. Diferentes estratégias o utilizam de maneiras distintas:
|
Estratégia |
Propósito do uniqueId |
|
Default |
Não utilizado |
|
ReusePool |
Não utilizado |
|
IdScoped |
ID principal. O mesmo uniqueId sempre retorna a mesma instância. |
|
Singleton |
Não utilizado |
Referência de exemplo
O módulo PlayerKitUsages/UsageLifecycleStrategy fornece um exemplo completo de como usar as estratégias de ciclo de vida do player. Ele demonstra a troca entre as quatro estratégias integradas (Default, ReusePool, Singleton e IdScopedPool). Também mostra o comportamento de reutilização de instâncias (NEW/REUSED/HIT) para reprodução de múltiplas source e o fluxo de limpeza de recursos para estratégias e controladores.