Todos os produtos
Search
Central de documentação

ApsaraVideo VOD:Estratégia de ciclo de vida do player

Última atualização: Sep 11, 2026

A estratégia de ciclo de vida do player é um componente arquitetônico central do AliPlayerKit. Ela unifica o gerenciamento da criação, reutilização, reciclagem e destruição de instâncias do player, permitindo agendamento de recursos mais eficiente e otimização de desempenho em diferentes cenários de negócios.

Introdução

O que é uma estratégia de ciclo de vida do player?

A 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 essenciais como aquisição, reciclagem e limpeza dessas instâncias, desacoplando o gerenciamento de recursos do player da lógica de negócios.

Cenários de negócios distintos apresentam requisitos diferentes para o gerenciamento de instâncias do player:

Cenário

Requisitos

Estratégia recomendada

Reprodução de vídeo normal

Simples e direta, sem necessidade de reutilização

Default

Lista de vídeos curtos

Troca frequente, exige 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 à memória

Instância global única, uso mínimo de memória

Singleton

Valor principal

Gerenciar o ciclo de vida do player com um padrão de estratégia oferece as seguintes vantagens fundamentais:

  • Desacoplamento: A 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 estratégias diferentes em tempo de execução sem alterar a 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 simplifica o monitoramento e a depuração.

Contexto do design

A estratégia de ciclo de vida do player teve origem no pool de players multi-instância da solução de minisséries da Alibaba Cloud. Foi projetada para atender a requisitos rigorosos de tempo até o primeiro quadro (TTFF), transição suave 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 para gerenciar o ciclo de vida do player.

Recursos

Capacidades principais

Capacidade

Descrição

Aquisição de instância

acquirePlayer obtém uma instância do player. A estratégia decide se cria uma nova ou reutiliza uma existente.

Reciclagem de instância

recyclePlayer:force: recicla uma instância. A estratégia decide se a destrói ou mantém.

Limpeza de recursos

clear limpa todas as instâncias do player mantidas pela estratégia e restaura o estado inicial.

Pré-carregamento

preloadWithCount: pré-cria instâncias no pool para reduzir o TTFF (@optional).

Vinculação de ID

acquirePlayerWithUniqueId: obtém uma instância por um ID de negócio exclusivo (@optional).

Injeção de fábrica

setupWithFactory: injeta uma fábrica de players. O AliPlayerController chama esse método automaticamente.

Estratégias integradas

O AliPlayerKit fornece quatro estratégias de ciclo de vida do player integradas:

Estratégia

Nome da classe

Descrição

Cenários

Estratégia padrão

DefaultLifecycleStrategy

Cria uma nova instância a cada vez. Destrói-a imediatamente após o uso.

Reprodução normal

Estratégia de pool de reutilização

ReusePoolLifecycleStrategy

Mantém um pool ocioso. Prioriza a reutilização de instâncias do pool.

Lista de vídeos curtos

Política de vinculação de ID

IdScopedPoolLifecycleStrategy

Mantém uma instância separada para cada uniqueId. Remove instâncias usando um algoritmo LRU (Least Recently Used).

Pré-carregamento de vídeo

Estratégia singleton

SingletonLifecycleStrategy

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 à 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 padrão

Esta é a maneira mais simples de usar o player. Nenhuma configuração extra é necessária. O AliPlayerController usa a 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 padrão: 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ídeo curto)

Esta estratégia é adequada 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];
Nota

O AliPlayerController chama automaticamente [strategy setupWithFactory:[AliPlayerKit playerFactory]] para injetar a fábrica 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)

Esta estratégia é ideal para cenários que exigem pré-carregamento e alternância 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)

Esta estratégia utiliza 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];
Nota

Ao usar a estratégia singleton, várias instâncias de AliPlayerController não podem manter o player simultaneamente. Isso causaria conflitos de estado. O método init da SingletonLifecycleStrategy está marcado como NS_UNAVAILABLE. Obtenha a instância apenas por meio de +sharedInstance.

Referência de cenário: Reprodução em lista

O ScenePlaylistViewController apresenta um exemplo completo de uso da 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];
}
Nota

Em um cenário de reprodução em lista, a SingletonLifecycleStrategy reutiliza a instância do player. Isso evita a sobrecarga de desempenho decorrente da criação e destruição frequentes. Ao trocar de vídeo, o método configure: executa automaticamente recycle(old instance) + acquire(new instance). Não é necessário gerenciar 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

Características:

  • Sem estado. Cria uma nova instância por meio da fábrica para cada chamada de acquirePlayer.

  • Destrói a instância diretamente a cada chamada de recyclePlayer:force:, independentemente do valor de force.

  • Menor uso de memória (liberada após o uso).

  • Indicada para a maioria dos cenários de reprodução padrão.

Fluxo principal:

Operação

Comportamento

acquirePlayer

Cria uma nova instância por meio da fábrica

recyclePlayer:force:

Destrói a instância diretamente, independentemente do valor de force

clear

Nenhuma operação (não mantém um pool)

ReusePoolLifecycleStrategy

Esta estratégia baseia-se no padrão de pool de objetos. 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

Características:

  • Prioriza a reutilização de instâncias do pool ocioso para reduzir a sobrecarga de inicialização do player.

  • Suporta preloadWithCount: para preencher previamente o pool.

  • A capacidade do pool é controlada por maxPoolSize.

  • Todos os métodos são thread-safe.

  • Projetada para listas de vídeos curtos e cenários de feed.

Fluxo principal:

Operação

Comportamento

acquirePlayer

Obtém uma instância do pool ocioso primeiro. Se o pool estiver vazio, cria uma nova instância por meio da fábrica.

recyclePlayer:force:NO

Interrompe a reprodução e devolve a instância ao pool ocioso. Se o pool estiver cheio, destrói a instância.

recyclePlayer:force:YES

Destrói a instância imediatamente.

clear

Destrói todas as instâncias no pool ocioso. As instâncias ativas não são afetadas.

preloadWithCount:

Pré-cria instâncias e as adiciona ao pool ocioso. A quantidade é limitada por maxPoolSize.

IdScopedPoolLifecycleStrategy

Esta estratégia mantém uma instância de player separada para cada uniqueId. O mesmo uniqueId sempre retorna a mesma instância. Utiliza 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

Características:

  • Vinculação de ID. O mesmo uniqueId sempre reutiliza a mesma instância.

  • O mecanismo de remoção LRU limpa automaticamente as instâncias usadas menos recentemente.

  • 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 multi-instância na solução de minisséries da Alibaba Cloud.

  • Recomendada para pré-carregamento de vídeo e cenários de alternância entre múltiplos vídeos.

Fluxo principal:

Operação

Comportamento

acquirePlayerWithUniqueId: (ID encontrado)

Retorna a instância existente e atualiza sua posição na ordem LRU.

acquirePlayerWithUniqueId: (ID não encontrado)

Obtém uma instância da fila de pré-carregamento primeiro. Caso contrário, cria uma nova instância e a vincula ao ID.

recyclePlayer:uniqueId:force:NO

Apenas interrompe a reprodução. A instância permanece na tabela de mapeamento e é removida automaticamente pelo algoritmo LRU.

recyclePlayer:uniqueId:force:YES

Remove a instância da tabela de mapeamento e a destrói imediatamente.

clear

Limpa as instâncias na fila de pré-carregamento e na tabela de mapeamento.

preloadWithCount:

Cria instâncias sem um ID vinculado. Estas são usadas na primeira vez que um novo ID é adquirido.

Nota

Se uma estratégia implementar o método acquirePlayerWithUniqueId:, o AliPlayerController o chamará em vez de acquirePlayer. Isso permite a vinculação de ID por meio de VideoSource.uniqueId. Da mesma forma, recyclePlayer:uniqueId:force: é chamado preferencialmente em relação a recyclePlayer:force:.

SingletonLifecycleStrategy

Esta 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

Características:

  • Globalmente única. Todos os controladores que usam esta estratégia compartilham a mesma instância do player.

  • Menor consumo de memória.

  • clear é uma operação nula. Não destrói a instância singleton. Destrua-a explicitamente chamando recyclePlayer:force:YES.

  • Não recomendada para cenários onde vários vídeos são reproduzidos simultaneamente.

  • Várias instâncias de AliPlayerController não podem manter o player simultaneamente. Isso causaria conflitos de estado.

Fluxo principal:

Operação

Comportamento

acquirePlayer

Retorna a instância global se ela existir. Caso contrário, cria-a.

recyclePlayer:force:NO

Apenas interrompe a reprodução. A instância é retida.

recyclePlayer:force:YES

Destrói a instância global.

clear

Operação nula (não destrói a instância singleton).

Tabela comparativa de estratégias

Estratégia

Comportamento de aquisição

Comportamento de reciclagem (force:NO)

Cenários

TTFF

Thread safety

Default

Novo para cada item

Destruição imediata

Reprodução normal

Lento

ReusePool

Obter do pool / Criar novo

Devolver ao pool / Destruir se cheio

Lista de vídeos curtos

Rápido

Sim

IdScoped

ID encontrado / Pré-preenchido / Criar novo

Manter na tabela de mapeamento / Remover por LRU

Pré-carregamento

Mais rápido

Sim

Singleton

Criar apenas uma vez

Apenas interromper 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
Nota

O AliPlayerController chama setupWithFactory: automaticamente durante a chamada initWithLifecycleStrategy: para injetar a instância de fábrica retornada por [AliPlayerKit playerFactory]. Geralmente, os desenvolvedores não precisam chamar este método manualmente. Para pré-carregar instâncias antes de criar um controlador, chame manualmente setupWithFactory: e depois preloadWithCount:.

Classe base de estratégia (BaseLifecycleStrategy)

A BaseLifecycleStrategy é a classe base compartilhada para todas as estratégias integradas. Fornece gerenciamento de fábrica e métodos de modelo:

@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
Nota

A própria 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 em instâncias do player, em vez de chamar a factory diretamente. Isso garante que as operações sejam registradas uniformemente.

Fábrica de players (PlayerFactory)

O protocolo PlayerFactory define a interface para criar e destruir 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 a DefaultPlayerFactory integrada, que usa o Alibaba Cloud Player SDK (AliPlayer) para criar instâncias padrão. Substitua-a por uma fábrica 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 recursos da estratégia

Momento

Operação

Descrição

Troca de vídeo

configure: Reciclagem + aquisição internas

Automático, nenhuma operação manual necessária

Destruição do controlador

O método destroy chama internamente recyclePlayer:force:YES.

Automático

Saída da página

Chame [controller destroy] em dealloc

Deve ser chamado manualmente

Liberação de recursos do pool

[strategy clear]

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 produto de vídeo normal

Default

Simples e direta. 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 suavidade 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 básicos / Pouca memória

Singleton

Instância global única para uso mínimo 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 avisos de memória

Estratégias baseadas em pool devem ouvir UIApplicationDidReceiveMemoryWarningNotification e chamar clear.

Defina uma capacidade de pool razoável

Cada instância do player usa cerca de 35 MB a 40 MB de memória. Defina maxPoolSize com base no desempenho do dispositivo.

Libere o pool ocioso em segundo plano

Chame clear para liberar instâncias ociosas quando o aplicativo entrar em segundo plano.

Chame destroy quando a página for destruída

Chame [controller destroy] em dealloc. Caso contrário, ocorrerá um vazamento de memória.

// 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 de página

Chame [controller destroy] em dealloc

Evita vazamentos de memória

Limpeza de estratégia

O último usuário chama [strategy clear]

Libera instâncias ociosas no pool

Estratégia singleton

Não permita que vários controladores mantenham o player simultaneamente

Evita conflitos de estado

Injeção de fábrica

Não chame setupWithFactory: manualmente

O controlador a injeta automaticamente e o método é idempotente (apenas a primeira chamada tem efeito).

Pré-carregamento

Chame após a criação do controlador

A fábrica é 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

PlayerLifecycleStrategy

Protocolo de estratégia de ciclo de vida. Define interfaces para adquirir, reciclar e limpar instâncias.

BaseLifecycleStrategy

Classe base de estratégia. Fornece gerenciamento de fábrica e métodos de modelo createPlayer/destroyPlayer:.

PlayerFactory

Protocolo de fábrica de players. Define interfaces para criar e destruir instâncias.

DefaultPlayerFactory

Implementação de fábrica padrão. Usa o Alibaba Cloud Player SDK para criar instâncias.

MediaPlayer

Protocolo de 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

DefaultLifecycleStrategy

[[... alloc] init]

ReusePoolLifecycleStrategy

[[... alloc] initWithMaxPoolSize:]

maxPoolSize, idleCount, activeCount

IdScopedPoolLifecycleStrategy

[[... alloc] initWithMaxPoolSize:]

maxPoolSize, poolCount

SingletonLifecycleStrategy

[... sharedInstance]

Métodos de PlayerLifecycleStrategy

Método

Obrigatório

Descrição

setupWithFactory:

Sim

Injeta a fábrica de players. Chamado automaticamente pelo controlador.

acquirePlayer

Sim

Obtém uma instância do player.

recyclePlayer:force:

Sim

Recicla uma instância do player.

clear

Sim

Libera todas as instâncias em cache.

preloadWithCount:

Não

Pré-carrega instâncias. Implementado por ReusePool e IdScoped.

acquirePlayerWithUniqueId:

Não

Obtém uma instância por uniqueId. Implementado por IdScoped.

recyclePlayer:uniqueId:force:

Não

Recicla uma instância por uniqueId. Implementado por IdScoped.

Métodos de BaseLifecycleStrategy

Método/Propriedade

Descrição

factory

A fábrica de players atualmente injetada (somente leitura).

setupWithFactory:

Injeta a fábrica. Idempotente, apenas a primeira chamada tem efeito.

createPlayer

Cria uma instância por meio da fábrica com registro uniforme.

destroyPlayer:

Destrói uma instância por meio da fábrica com registro uniforme.

Descrição do parâmetro force

Valor de force

Comportamento

Cenário

NO

A estratégia decide se devolve a instância ao pool ou apenas interrompe a reprodução.

Troca normal de vídeo. Usado dentro de configure:.

YES

Destrói a instância imediatamente, independentemente da estratégia.

Destruição do controlador. Usado dentro de destroy.

Descrição de uniqueId

uniqueId é uma propriedade de identificador de negócio exclusivo em VideoSource usada para distinguir diferentes fontes de vídeo. Diferentes estratégias o utilizam de maneiras distintas:

Estratégia

Finalidade do uniqueId

Default

Não utilizado

ReusePool

Não utilizado

IdScoped

Identificador 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 estratégias de ciclo de vida do player. Demonstra a alternância entre as quatro estratégias integradas (Default, ReusePool, Singleton e IdScopedPool). Mostra também o comportamento de reutilização de instância (NEW/REUSED/HIT) para reprodução de múltiplas fontes e o fluxo de limpeza de recursos para estratégias e controladores.