Mobile · JúniorJunior

Ciclo de vida de um app: estados, telas e o básico que muda tudo

Todo app vive numa montanha-russa de estados: ora está na sua frente recebendo toques, ora foi empurrado para trás quando chegou uma ligação, ora foi simplesmente encerrado pelo sistema para liberar memória. Entender esse ciclo de vida é o primeiro passo para escrever apps que não perdem dados nem travam quando o usuário troca de tela. É um conhecimento que você usa todo dia e que aparece logo nas primeiras conversas técnicas.

Os estados de um app

Independente de iOS, Android, React Native ou Flutter, um app transita entre alguns estados fundamentais. A nomenclatura muda, mas a ideia é a mesma.

  • Primeiro plano (foreground / ativo): o app está visível e recebendo eventos de toque. É onde tudo "acontece".
  • Segundo plano (background): o usuário saiu (apertou home, abriu outro app), mas o seu app ainda está vivo na memória. Você tem pouco tempo e recursos limitados aqui.
  • Suspenso (inativo / suspended): continua em memória, mas não executa código. Um estado de "pausa congelada".
  • Encerrado (terminated): o processo foi destruído. Ao voltar, o app inicia do zero.

Diagrama dos estados

   [Não iniciado]
        |
        v
   [Foreground] <----+
     |    ^          |
 (sai)|   |(volta)   |
     v    |          |
   [Background]      |
     |                |
 (SO libera memória) |
     v                |
   [Encerrado] -------+ (inicia do zero)

O que acontece quando o usuário sai e volta

Imagine o app como uma pessoa lendo um livro. Quando alguém a interrompe, ela pode marcar a página (salvar estado) ou simplesmente fechar o livro de qualquer jeito. Se o sistema operacional decidir "matar" o app em segundo plano para dar memória a outro, ao voltar o usuário espera continuar de onde parou — não recomeçar do início.

O ponto crítico: voltar de background (app vivo) é diferente de voltar de encerrado (app morto). No primeiro caso seu estado em memória ainda existe; no segundo, não. Tratar os dois como iguais é fonte de bug.

Salvar e restaurar estado

Cada plataforma oferece ganchos para você persistir o necessário antes de perder a memória: no Android há o onSaveInstanceState, no iOS o state restoration, e frameworks como Flutter têm seus equivalentes. A regra é salvar o mínimo para reconstruir a tela: texto digitado, posição de rolagem, item selecionado.

// pseudo-código ao ir para background
aoSalvarEstado(bundle) {
  bundle.put("rascunho", campoTexto.valor)
  bundle.put("scrollY", lista.posicao)
}

aoRestaurar(bundle) {
  campoTexto.valor = bundle.get("rascunho")
}

Por que isso importa: rotação e app morto

No Android, girar a tela recria a tela inteira por padrão — é tecnicamente o mesmo mecanismo de "morrer e renascer". Se você não salvou estado, o formulário meio preenchido some. É comum em entrevista pedir para explicar exatamente o que acontece ao rotacionar a tela e como evitar a perda de dados — a resposta esperada passa por entender esse ciclo.

Bugs comuns de ignorar o ciclo de vida

  • Vazamento de recursos: registrar um listener ou abrir a câmera no foreground e esquecer de liberar no background.
  • Timers e requisições zumbis: continuar atualizando a UI de uma tela que já não está visível.
  • Estado perdido na rotação: o clássico formulário que zera ao girar o celular.
  • Assumir que o app nunca morre: guardar dados só em memória e perder tudo quando o SO recupera recursos.
O sistema operacional é o dono da memória, não o seu app. Programe esperando ser interrompido e encerrado a qualquer momento — quem assume isso escreve apps robustos.

Conclusão

O ciclo de vida define quando seu código roda e quando seus dados sobrevivem. Dominar os estados (foreground, background, suspenso, encerrado), saber a diferença entre voltar vivo e renascer do zero, e salvar/restaurar o essencial é a base sobre a qual todo o resto se apoia — inclusive a navegação entre telas.

Every app lives on a rollercoaster of states: sometimes it is right in front of you receiving taps, sometimes it gets pushed to the back when a call comes in, and sometimes it is simply killed by the system to free up memory. Understanding this lifecycle is the first step toward writing apps that don't lose data or crash when the user switches screens. It is knowledge you use every day, and it comes up in the very first technical conversations.

The states of an app

Regardless of iOS, Android, React Native or Flutter, an app moves between a few fundamental states. The naming changes, but the idea is the same.

  • Foreground (active): the app is visible and receiving touch events. This is where everything "happens".
  • Background: the user left (pressed home, opened another app), but your app is still alive in memory. You have little time and limited resources here.
  • Suspended (inactive): still in memory, but not executing code. A "frozen pause" state.
  • Terminated: the process was destroyed. When the user returns, the app starts from scratch.

State diagram

   [Not started]
        |
        v
   [Foreground] <----+
     |    ^          |
 (leave)|  |(return)  |
     v    |          |
   [Background]      |
     |                |
 (OS frees memory)   |
     v                |
   [Terminated] ------+ (starts from scratch)

What happens when the user leaves and comes back

Picture the app as a person reading a book. When someone interrupts them, they can put in a bookmark (save state) or just slam the book shut. If the operating system decides to "kill" the app in the background to give memory to another one, the user expects to pick up where they left off when they return — not start over.

The critical point: coming back from background (app alive) is different from coming back from terminated (app dead). In the first case your in-memory state still exists; in the second, it doesn't. Treating both as the same is a source of bugs.

Saving and restoring state

Each platform offers hooks so you can persist what you need before memory is lost: Android has onSaveInstanceState, iOS has state restoration, and frameworks like Flutter have their own equivalents. The rule is to save the minimum needed to rebuild the screen: typed text, scroll position, selected item.

// pseudo-code when going to background
onSaveState(bundle) {
  bundle.put("draft", textField.value)
  bundle.put("scrollY", list.position)
}

onRestore(bundle) {
  textField.value = bundle.get("draft")
}

Why this matters: rotation and killed apps

On Android, rotating the screen recreates the entire screen by default — technically it is the same "die and be reborn" mechanism. If you didn't save state, the half-filled form vanishes. Interviewers often ask you to explain exactly what happens when the screen rotates and how to avoid losing data — the expected answer hinges on understanding this lifecycle.

Common bugs from ignoring the lifecycle

  • Resource leaks: registering a listener or opening the camera in the foreground and forgetting to release it in the background.
  • Zombie timers and requests: continuing to update the UI of a screen that is no longer visible.
  • State lost on rotation: the classic form that resets when you turn the phone.
  • Assuming the app never dies: keeping data only in memory and losing everything when the OS reclaims resources.
The operating system owns the memory, not your app. Program expecting to be interrupted and terminated at any moment — whoever assumes this writes robust apps.

Conclusion

The lifecycle defines when your code runs and when your data survives. Mastering the states (foreground, background, suspended, terminated), knowing the difference between returning alive and being reborn from scratch, and saving/restoring the essentials is the foundation everything else rests on — including navigation between screens.

Leia também

Voltar à trilhaBack to the track