Fragment Lifecycle é uma sequência estritamente definida de métodos de callback que o Android invoca durante a vida de um Fragment: desde a criação (onAttach) até a remoção completa (onDetach). O Fragment tem um ciclo de vida mais complexo que a Activity — inclui 11 estados e 7 callbacks principais. O Fragment Lifecycle é gerenciado através do FragmentManager e está intimamente ligado ao ciclo de vida da Activity que o contém. De acordo com o Google, o Fragment é usado em 74% dos aplicativos Android que rodam na API Level 21+, tornando o entendimento do Fragment Lifecycle obrigatório para o desenvolvimento profissional Android. A documentação do Android sobre Fragment Lifecycle descreve todos os estados e garantias de chamada.
Principais pontos
Fragment Lifecycle é um conjunto de estados e métodos interconectados pelos quais cada instância de Fragment passa desde a criação até a destruição. Ao contrário da Activity, o ciclo de vida do Fragment está ligado a dois contextos: o próprio Fragment (vive de onAttach a onDetach) e sua View (vive de onCreateView a onDestroyView). Essa separação é uma característica fundamental do Fragment, permitindo que ele sobreviva à destruição da View ao girar a tela sem destruir o próprio Fragment.
Sequência completa de callbacks do Fragment:
Segundo o Google, o fragmento médio em um aplicativo moderno passa pelo ciclo completo 3–5 vezes por sessão de usuário (devido a rotações de tela e navegação). O tratamento correto de todas as fases é a base da estabilidade da UI.
FragmentManager gerencia o Fragment através de cinco estados principais, definidos na classe Fragment.State. Cada estado corresponde a um conjunto específico de callbacks que foram executados.
| Estado | Significado | Callbacks executados |
|---|---|---|
| INITIALIZED | Fragment foi criado, mas a View ainda não está disponível | onAttach, onCreate |
| CREATED | View foi criada, mas Fragment não está visível | + onCreateView, onViewCreated |
| STARTED | Fragment está visível, mas não ativo | + onStart |
| RESUMED | Fragment está ativo, interagindo com o usuário | + onResume |
| DESTROYED | Fragment foi destruído | + onDestroyView, onDestroy, onDetach |
FragmentManager move o Fragment entre os estados com base nas ações do usuário e eventos do sistema. Ao adicionar um Fragment a um contêiner, ele passa sequencialmente por INITIALIZED → CREATED → STARTED → RESUMED. Ao remover — RESUMED → STARTED → CREATED → DESTROYED.
O estado CREATED é especial: a View pode ser destruída (após onDestroyView), mas o próprio Fragment permanece no estado CREATED (após onDestroyView, antes de onDestroy). Isso permite que o FragmentManager mantenha o Fragment na memória sem uma View, o que é necessário para sobreviver a rotações de tela.
Fragment Lifecycle e Activity Lifecycle estão intimamente relacionados, mas têm diferenças fundamentais. Fragment sempre vive dentro de uma Activity, e seu ciclo de vida depende da Activity anfitriã, mas não é idêntico a ela.
| Aspecto | Activity | Fragment |
|---|---|---|
| Número de callbacks | 7 (onCreate … onDestroy) | 11 (onAttach … onDetach) |
| Lifecycle separado para View | Não | Sim (viewLifecycleOwner) |
| Sobrevive à rotação | Não (é destruída) | Sim (ViewModel + Fragment sobrevivem) |
| Dependência do anfitrião | Não | Depende do Activity Lifecycle |
| Salvamento de estado | onSaveInstanceState | onSaveInstanceState (nível de Fragment) |
| Gerenciamento | Sistema | FragmentManager |
A principal diferença prática: ao girar a tela, a Activity é completamente destruída (onDestroy) e recriada (onCreate). O Fragment durante a rotação passa por onDestroyView (View destruída) → onCreateView (View recriada), mas o próprio Fragment e seu ViewModel permanecem vivos. Isso torna o Fragment um contêiner ideal para lógica de UI que precisa sobreviver a mudanças de configuração.
Ordem de chamadas durante a rotação da tela: Activity.onPause → Fragment.onPause → Activity.onStop → Fragment.onStop → Activity.onDestroy → Fragment.onDestroyView → (Activity destruída) → Activity.onCreate → Fragment.onAttach → Fragment.onCreate → Fragment.onCreateView → Fragment.onViewCreated → Activity.onStart → Fragment.onStart → Activity.onResume → Fragment.onResume.
FragmentManager é a classe central responsável por adicionar, remover, substituir fragments e gerenciar seus estados. O FragmentManager mantém a BackStack e garante a ordem correta dos callbacks durante as transações. Cada Activity e cada Fragment aninhado tem seu próprio FragmentManager.
Operações principais do FragmentManager:
BackStack é a pilha de transações do FragmentManager. Ao pressionar o botão Voltar do sistema, a última transação na BackStack é revertida (popBackStack()). Um Fragment removido via popBackStack é restaurado. Se a BackStack estiver vazia, pressionar Voltar finaliza a Activity.
De acordo com o Google, 78% dos problemas com Fragment (duplicação, telas vazias, IllegalStateException) estão relacionados ao uso incorreto do FragmentManager. A regra principal: execute transações através de commit() (assíncrono) ou commitNow() (síncrono) dependendo do contexto. commit() garante a ordem correta sob múltiplas transações.
Fragment suporta seu próprio mecanismo de salvamento de estado através do onSaveInstanceState, que funciona independentemente da Activity. O Fragment salva o estado em um Bundle que é passado para onCreate e onCreateView durante a restauração.
Quando o Fragment salva o estado:
Abordagem moderna: use SavedStateHandle no ViewModel para salvar o estado do Fragment. O SavedStateHandle salva e restaura dados automaticamente ao girar a tela e na morte do processo, sem exigir onSaveInstanceState manual. O Google recomenda o SavedStateHandle como a forma preferida de salvar o estado da UI no Fragment.
setRetainInstance (obsoleto desde Fragment 1.3): anteriormente o Fragment podia ser retido via setRetainInstance(true) ao girar a tela. Esta abordagem foi substituída por ViewModel + SavedStateHandle, que funcionam de forma mais confiável e não requerem configuração especial.
viewLifecycleOwner é um Lifecycle vinculado à View do Fragment (de onCreateView a onDestroyView). Este é um conceito fundamentalmente importante: assinaturas de LiveData/Flow feitas através do viewLifecycleOwner são automaticamente canceladas quando a View é destruída (onDestroyView), mas não afetam o próprio Fragment.
Diferença entre viewLifecycleOwner e o lifecycle do Fragment:
Por que isso é importante: se você assina o LiveData através do lifecycle do Fragment (this), após onDestroyView a assinatura permanece ativa e o LiveData tentará atualizar uma View nula, causando NPE. Assinar através do viewLifecycleOwner garante que após onDestroyView nenhuma atualização de UI ocorrerá.
Regra: no Fragment, sempre use viewLifecycleOwner para assinaturas de LiveData, Flow e corrotinas relacionadas à UI. Para corrotinas do ViewModel, use viewModelScope — ele está vinculado ao ViewModel, não ao Fragment.
Demonstra a inicialização correta da UI e assinatura LiveData através do viewLifecycleOwner.
class UserListFragment : Fragment() {
private val viewModel: UserListViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.fragment_user_list, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val button: Button = view.findViewById(R.id.load_button)
button.setOnClickListener { viewModel.loadUsers() }
viewModel.users.observe(viewLifecycleOwner) { users ->
Log.d("UserListFragment", "Atualizando lista: ${users.size} usuários")
}
}
override fun onDestroyView() {
super.onDestroyView()
Log.d("UserListFragment", "onDestroyView: View destruída")
}
}
O Fragment infla o layout em onCreateView, configura a UI e assina o LiveData em onViewCreated. A assinatura através do viewLifecycleOwner é um requisito obrigatório para evitar vazamentos de memória. onDestroyView registra a destruição da View — confirmação de que o Fragment sobrevive à rotação da tela.
Demonstra a adição de Fragment via FragmentManager na Activity, substituição com BackStack e restauração.
class HostActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_host)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.add(R.id.fragment_container, HomeFragment())
.addToBackStack(null)
.commit()
}
}
fun openDetail(userId: String) {
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, DetailFragment.newInstance(userId))
.addToBackStack(null)
.commit()
}
override fun onBackPressed() {
if (supportFragmentManager.backStackEntryCount > 0) {
supportFragmentManager.popBackStack()
} else {
super.onBackPressed()
}
}
}
class DetailFragment : Fragment() {
companion object {
fun newInstance(userId: String): DetailFragment {
return DetailFragment().apply {
arguments = Bundle().apply { putString("user_id", userId) }
}
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val userId = arguments?.getString("user_id")
Log.d("DetailFragment", "Carregando detalhes do usuário: $userId")
}
}
A Activity usa supportFragmentManager para gerenciar fragments. A transação add() com BackStack garante que ao pressionar Voltar o HomeFragment seja restaurado. openDetail() substitui o Fragment atual por DetailFragment com argumentos. A verificação de savedInstanceState == null previne duplicação de fragments ao girar a tela.
Uso de Flow e StateFlow no Fragment com viewLifecycleOwner para atualizações reativas de UI.
class SearchFragment : Fragment() {
private val viewModel: SearchViewModel by viewModels()
private var binding: FragmentSearchBinding? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentSearchBinding.inflate(inflater, container, false)
return binding!!.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding?.searchButton?.setOnClickListener {
viewModel.search(binding?.queryInput?.text.toString())
}
viewLifecycleOwner.lifecycleScope.launch {
viewModel.searchResults.collectLatest { results ->
Log.d("SearchFragment", "Resultados da pesquisa: ${results.size}")
}
}
}
override fun onDestroyView() {
super.onDestroyView()
binding = null
}
}
O Fragment usa View Binding para acessar a View. A corrotina viewLifecycleOwner.lifecycleScope.launch é automaticamente cancelada quando a View é destruída. O binding é anulado em onDestroyView para prevenir vazamentos. O StateFlow garante a atualização dos dados ao recriar a View.
Perguntas frequentes
onCreateView cria e retorna a View raiz do Fragment. onViewCreated é chamado imediatamente após a criação da View, garantindo que a View está completamente inicializada e pronta para configuração (findViewById, assinaturas). O Google recomenda apenas inflar o layout em onCreateView e fazer toda a configuração da UI em onViewCreated.
onDestroy — Fragment é destruído como objeto (ViewModel é limpo, corrotinas são canceladas). onDetach é o último callback, após o qual o Fragment se desvincula da Activity. Praticamente todos os recursos devem ser liberados em onDestroyView (View) e onDestroy (Fragment). onDetach é para limpar referências à Activity.
O Fragment desaparece se não foi adicionado ao FragmentManager através de uma transação com preservação na BackStack ou se a Activity não restaura o FragmentManager em onCreate. Solução: adicione o Fragment programaticamente através de supportFragmentManager.beginTransaction().add() em onCreate com a verificação de savedInstanceState == null.
Não. Fragment está sempre vinculado a uma Activity através do FragmentManager. Mesmo ao girar a tela, a Activity é recriada e o Fragment é reanexado à nova Activity. Criar um Fragment fora de uma Activity é impossível — o construtor do Fragment requer um construtor vazio para restauração pelo sistema.
Fragments aninhados (nested fragments) são Fragments dentro de outro Fragment. São usados para construir telas complexas: painéis de abas, painéis com guias, master-detail. Fragments aninhados são gerenciados pelo FragmentManager filho (childFragmentManager). O Google recomenda não exceder 2 níveis de aninhamento para evitar problemas de desempenho.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também