Todos os produtos
Search
Central de documentação

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

Última atualização: Oct 14, 2026

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

acquirePlayer obtém uma instância do player. A estratégia decide se deve criar uma nova ou reutilizar uma existente.

Reciclagem de instância

recyclePlayer:force: recicla uma instância. A estratégia decide se deve destruí-la ou mantê-la.

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ócios exclusivo (@optional).

Injeção de factory

setupWithFactory: injeta uma factory de player. O AliPlayerController chama esse método automaticamente.

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

DefaultLifecycleStrategy

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

ReusePoolLifecycleStrategy

Mantém um pool ocioso. Reutiliza instâncias do pool primeiro.

Lista de vídeos curtos

Política de vinculação de ID

IdScopedPoolLifecycleStrategy

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

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 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];
Nota

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];
Nota

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];
}
Nota

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 de force.

  • 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

acquirePlayer

Crie uma nova instância através da factory

recyclePlayer:force:

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

clear

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

acquirePlayer

Obtém uma instância do pool ocioso primeiro. Se o pool estiver vazio, cria uma nova instância através da factory.

recyclePlayer:force:NO

Interrompe a reprodução e retorna 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. O número é limitado por maxPoolSize.

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 uniqueId sempre 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

acquirePlayerWithUniqueId: (ID hit)

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

acquirePlayerWithUniqueId: (ID miss)

Obtém uma instância da fila pré-carregada 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 é evictada 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 pré-carregada e na tabela de mapeamento.

preloadWithCount:

Cria instâncias sem um ID vinculado. Elas 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 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 chamando recyclePlayer: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 AliPlayerController não podem reter o player ao mesmo tempo. Isso causaria conflitos de estado.

Fluxo principal:

Operação

Comportamento

acquirePlayer

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

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

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
Nota

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

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.

Autocompletar

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

Você deve chamar [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 da página

Chame [controller destroy] em dealloc

Evita vazamentos de memória

Limpeza da estratégia

O último usuário chama [strategy clear]

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 setupWithFactory: manualmente

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

PlayerLifecycleStrategy

Protocolo de estratégia de ciclo de vida. Define interfaces para aquisição, reciclagem e limpeza de instâncias.

BaseLifecycleStrategy

Classe base da estratégia. Fornece gerenciamento de factory e métodos de modelo createPlayer/destroyPlayer:.

PlayerFactory

Protocolo da factory do player. Define interfaces para criação e destruição de instâncias.

DefaultPlayerFactory

Implementação da factory padrão. Usa o Alibaba Cloud Player SDK para criar instâncias.

MediaPlayer

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

DefaultLifecycleStrategy

[[... alloc] init]

—

ReusePoolLifecycleStrategy

[[... alloc] initWithMaxPoolSize:]

maxPoolSize, idleCount, activeCount

IdScopedPoolLifecycleStrategy

[[... alloc] initWithMaxPoolSize:]

maxPoolSize, poolCount

SingletonLifecycleStrategy

[... sharedInstance]

—

Métodos do PlayerLifecycleStrategy

Método

Obrigatório

Descrição

setupWithFactory:

Sim

Injeta a factory do player. 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 do BaseLifecycleStrategy

Método/Propriedade

Descrição

factory

A factory do player atualmente injetada (somente leitura).

setupWithFactory:

Injeta a factory. Idempotente, apenas a primeira chamada é efetiva.

createPlayer

Cria uma instância através da factory com registro em log uniforme.

destroyPlayer:

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

NO

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 configure:.

YES

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

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

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.