Ciclo de vida dos fragmentos

Cada instância Fragment tem um ciclo de vida próprio. Quando um usuário navega e interage com o app, os fragmentos passam por vários estados no ciclo de vida, à medida que são adicionados, removidos, entram ou saem da tela.

Para gerenciar o ciclo de vida, Fragment implementa LifecycleOwner, expondo um objeto Lifecycle que pode ser acessado com o método getLifecycle().

Cada estado Lifecycle possível é representado na enumeração Lifecycle.State.

Ao criar Fragment em um Lifecycle, é possível usar as técnicas e classes disponíveis para Gerenciar ciclos de vida com componentes que os reconhecem. Por exemplo, é possível exibir a localização do dispositivo na tela usando um componente com reconhecimento de ciclo de vida. Esse componente poderá começar a ouvir automaticamente quando o fragmento se tornar ativo e parar quando o fragmento passar para um estado inativo.

Como alternativa ao uso de um LifecycleObserver, a classe Fragment inclui métodos de callback que correspondem a cada uma das mudanças no ciclo de vida de um fragmento. Eles incluem onCreate(), onStart(), onResume(), onPause(), onStop() e onDestroy().

A visualização de um fragmento tem um Lifecycle separado, gerenciado de forma independente do Lifecycle do fragmento. Os fragmentos mantêm um LifecycleOwner para a visualização, que pode ser acessado usando getViewLifecycleOwner() ou getViewLifecycleOwnerLiveData(). Ter acesso ao Lifecycle da visualização é útil para situações em que um componente com reconhecimento de ciclo de vida só realiza o trabalho enquanto a visualização de um fragmento existe, como observar LiveData exibido somente na tela.

Este tópico aborda detalhadamente o ciclo de vida Fragment, explicando algumas das regras que determinam o estado do ciclo de vida de um fragmento e mostrando a relação entre os estados Lifecycle e os callbacks do ciclo de vida do fragmento.

Fragmentos e o gerenciador de fragmentos

Quando um fragmento é instanciado, ele começa no estado INITIALIZED. Para que um fragmento faça a transição ao longo do restante do ciclo de vida, ele precisa ser adicionado a um FragmentManager. O FragmentManager é responsável por determinar em qual estado o fragmento precisa estar e movê-lo para esse estado.

Além do ciclo de vida do fragmento, FragmentManager também é responsável por anexar fragmentos à atividade do host e removê-los quando o fragmento não estiver mais em uso. A classe Fragment tem dois métodos de callback, onAttach() e onDetach(), que podem ser substituídos para realizar o trabalho quando qualquer um desses eventos ocorrer.

O callback onAttach() é invocado quando o fragmento é adicionado ao FragmentManager e anexado à atividade do host. Nesse momento, o fragmento está ativo e o FragmentManager está gerenciando o estado do ciclo de vida. Então, os métodos FragmentManager, como findFragmentById(), retornam esse fragmento.

onAttach() é sempre chamado antes de qualquer mudança de estado do ciclo de vida.

O callback onDetach() é invocado quando o fragmento é removido de um FragmentManager e é separado da atividade do host. O fragmento não está mais ativo e não pode mais ser recuperado usando findFragmentById().

onDetach() é sempre chamado após qualquer mudança de estado do ciclo de vida.

Esses callbacks não estão relacionados aos métodos FragmentTransaction, attach() e detach(). Para ver mais informações sobre esses métodos, consulte Transações de fragmentos.

Estados de ciclo de vida dos fragmentos e callbacks

Ao determinar o estado do ciclo de vida de um fragmento, FragmentManager considera o seguinte:

  • O estado máximo de um fragmento é determinado pelo FragmentManager. Um fragmento não pode progredir para além do estado do FragmentManager.
  • Como parte de uma FragmentTransaction, é possível definir um estado de ciclo de vida máximo em um fragmento usando setMaxLifecycle().
  • O estado do ciclo de vida de um fragmento nunca pode ser maior do que o pai. Por exemplo, um fragmento pai ou uma atividade mãe precisa ser iniciado antes dos fragmentos filhos. Da mesma forma, os fragmentos filhos precisam ser interrompidos antes do fragmento pai ou da atividade mãe.
Os estados do ciclo de vida dos fragmentos e a relação com
            os callbacks do ciclo de vida e o ciclo de vida da visualização do fragmento.
Figura 1. Estados de Lifecycle de fragmento e a relação deles com os callbacks do ciclo de vida do fragmento e a Lifecycle da visualização do fragmento.

A Figura 1 mostra cada um dos estados Lifecycle do fragmento e como eles estão relacionados aos callbacks do ciclo de vida do fragmento e ao Lifecycle da visualização do fragmento.

À medida que um fragmento avança pelo ciclo de vida, ele se move para cima e para baixo entre os estados. Por exemplo, um fragmento adicionado à parte superior da pilha de retorno avança para cima de CREATED para STARTED e para RESUMED. Por outro lado, quando um fragmento é retirado da pilha de retorno, ele se move para baixo entre os estados, passando de RESUMED para STARTED, para CREATED e, por fim, para DESTROYED.

Transições de estado para cima

Ao avançar para cima entre os estados de ciclo de vida, um fragmento chama primeiro o callback do ciclo de vida associado ao novo estado. Quando o callback é concluído, o Lifecycle.Event relevante é enviado aos observadores pelo Lifecycle do fragmento, seguido do Lifecycle da visualização do fragmento, se instanciado.

Fragmento CREATED

Quando o fragmento atinge o estado CREATED, ele foi adicionado a um FragmentManager e o método onAttach() já foi chamado.

Esse seria o local correto para restaurar qualquer estado salvo associado ao próprio fragmento com o SavedStateRegistry do fragmento. Nesse momento, a visualização do fragmento ainda não foi criada. Qualquer estado associado à visualização precisa ser restaurado somente depois que ela for criada.

Essa transição invoca o callback onCreate(). O callback também recebe um argumento savedInstanceState Bundle contendo qualquer estado salvo anteriormente por onSaveInstanceState(). savedInstanceState tem valor null na primeira vez que o fragmento é criado, mas é sempre não nulo para criações posteriores, mesmo que você não substitua onSaveInstanceState(). Consulte Como salvar o estado com fragmentos para ver mais detalhes.

Fragmento CREATED e visualização INITIALIZED

O Lifecycle da visualização do fragmento é criado somente quando o Fragment fornece uma instância válida de View. Na maioria dos casos, é possível usar os construtores de fragmento contendo um @LayoutId, que infla a visualização automaticamente no momento certo. Você também pode substituir onCreateView() para inflar ou criar a visualização do fragmento de forma programática.

Somente se a visualização do fragmento for instanciada com um valor de View não nulo, essa View será definida no fragmento e poderá ser recuperada usando getView(). Então, o getViewLifecycleOwnerLiveData() será atualizado com o LifecycleOwner INITIALIZED, correspondente à visualização do fragmento. O callback do ciclo de vida de onViewCreated() também é chamado nesse momento.

Esse é o local adequado para configurar o estado inicial da sua visualização, para começar a observar instâncias de LiveData com callbacks que atualizam a visualização do fragmento e para configurar adaptadores em qualquer instância RecyclerView ou ViewPager2 na visualização do fragmento.

Fragmento e visualização CREATED

Depois que a visualização do fragmento é criada, o estado anterior da visualização, se houver, é restaurado e o Lifecycle da visualização é movido para o estado CREATED. O proprietário do ciclo de vida da visualização também emite o evento ON_CREATE para os observadores. Nesse momento, é necessário restaurar qualquer outro estado associado à visualização do fragmento.

Essa transição também invoca o callback onViewStateRestored().

Fragmento e visualização STARTED

É altamente recomendável vincular componentes com reconhecimento de ciclo de vida ao estado STARTED de um fragmento, já que esse estado garante que a visualização do fragmento esteja disponível, se criada, e que é seguro executar uma FragmentTransaction no FragmentManager filho do fragmento. Se a visualização do fragmento não for nula, o Lifecycle dessa visualização será movido para STARTED imediatamente depois que o Lifecycle do fragmento for movido para STARTED.

Quando o fragmento se torna STARTED, o callback onStart() é invocado.

Fragmento e visualização RESUMED

Quando o fragmento estiver visível, todos os efeitos de Animator e Transition terão sido concluídos e o fragmento estará pronto para a interação do usuário. O Lifecycle do fragmento é movido para o estado RESUMED, e o callback onResume() é invocado.

A transição para RESUMED é o sinal adequado para indicar que o usuário agora pode interagir com o fragmento. Fragmentos que não são RESUMED não podem definir o foco manualmente nas visualizações nem tentar processar a visibilidade do método de entrada.

Transições de estado para baixo

Quando um fragmento se move para baixo para um estado de ciclo de vida inferior, o Lifecycle.Event relevante é emitido para os observadores pelo Lifecycle da visualização do fragmento, se instanciado, seguido pelo Lifecycle do fragmento. Depois que o evento de ciclo de vida de um fragmento é emitido, o fragmento chama o callback do ciclo de vida associado.

Fragmento e visualização STARTED

À medida que o usuário começa a sair do fragmento e este ainda está visível, os Lifecycles do fragmento e da visualização são movidos de volta para o estado STARTED e emitem o evento ON_PAUSE para os observadores. Em seguida, o fragmento invoca o callback onPause().

Fragmento e visualização CREATED

Quando o fragmento não está mais visível, os Lifecycles do fragmento e a visualização são movidos para o estado CREATED e emitem o evento ON_STOP para os observadores. Essa transição de estado é acionada não somente quando a atividade ou fragmento pai é interrompido, mas também quando o estado é salvo pela atividade ou fragmento pai. Esse comportamento garante que o evento ON_STOP seja invocado antes que o estado do fragmento seja salvo. Isso torna o evento ON_STOP o último ponto em que é seguro realizar uma FragmentTransaction no FragmentManager filho.

Conforme mostrado na figura 2, a ordem do callback onStop() e o salvamento do estado com onSaveInstanceState() são diferentes com base no nível da API. Para todas as APIs de níveis anteriores ao 28, onSaveInstanceState() é invocado antes de onStop(). Para as APIs de nível 28 e mais recentes, a ordem de chamada é revertida.

Diferenças de ordem de chamada para onStop() e onSaveInstanceState()
Figura 2. Diferenças na ordem de chamada de onStop() e onSaveInstanceState().

Fragmento CREATED e visualização DESTROYED

Depois que todas as animações e transições de saída são concluídas e a visualização do fragmento é removida da janela, o Lifecycle da visualização do fragmento é movido para o estado DESTROYED e emite o evento ON_DESTROY para os observadores. Em seguida, o fragmento invoca o callback onDestroyView(). Nesse momento, a visualização do fragmento atinge o fim do ciclo de vida e getViewLifecycleOwnerLiveData() retorna um valor null.

Então, todas as referências à visualização do fragmento precisam ser removidas, permitindo que a visualização do fragmento seja coletada como lixo.

Fragmento DESTROYED

Se o fragmento for removido ou se o FragmentManager for destruído, o Lifecycle do fragmento será movido para o estado DESTROYED e enviará o evento ON_DESTROY aos observadores. Em seguida, o fragmento invoca o callback onDestroy(). Nesse momento, o fragmento atinge o fim do ciclo de vida.

Outros recursos

Para ver mais informações relacionadas ao ciclo de vida do fragmento, consulte os recursos a seguir.

Guias

Blogs