¿Por qué importa el ciclo de vida?
Android puede destruir y recrear tu Activity en cualquier momento: al rotar el dispositivo, cuando el sistema necesita memoria, o cuando el usuario cambia de app. Si no manejás el ciclo de vida correctamente, tu app va a tener bugs difíciles de reproducir: datos perdidos al rotar, memory leaks, crashes en background.
Entender el ciclo de vida es la diferencia entre una app estable y una que crashea.
Los métodos del ciclo de vida
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// La Activity se crea. Inflá el layout, inicializá variables,
// configurá listeners. Se llama una sola vez (o al recrearse).
}
override fun onStart() {
super.onStart()
// La Activity es visible pero aún no interactuable.
// Poco usado en la práctica.
}
override fun onResume() {
super.onResume()
// La Activity está en primer plano y el usuario puede interactuar.
// Iniciá animaciones, sensores, cámara, actualizaciones de UI.
}
override fun onPause() {
super.onPause()
// Otra Activity va a tomar el foco (dialog, nueva pantalla).
// Pausá animaciones, liberá recursos que consumen batería.
// Guardá datos críticos acá (puede ser el último método llamado).
}
override fun onStop() {
super.onStop()
// La Activity ya no es visible. Liberá recursos pesados.
// No hagas operaciones largas acá: el sistema puede matarte.
}
override fun onDestroy() {
super.onDestroy()
// La Activity se va a destruir definitivamente.
// Liberá todo lo que quede: listeners, conexiones, etc.
}
}
Flujos típicos
- App se abre por primera vez:
onCreate → onStart → onResume - Usuario presiona Home:
onPause → onStop - Usuario vuelve a la app:
onRestart → onStart → onResume - Usuario rota el dispositivo:
onPause → onStop → onDestroy → onCreate → onStart → onResume - Usuario presiona Back:
onPause → onStop → onDestroy
La rotación recrea la ActivityCuando el usuario rota el dispositivo, Android destruye y recrea la Activity. Todo lo que guardaste en variables de instancia se pierde. Esto sorprende a muchos devs nuevos.
Guardar estado con savedInstanceState
Para guardar datos simples ante la recreación, usás onSaveInstanceState:
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("TEXTO_USUARIO", binding.etNombre.text.toString())
outState.putInt("CONTADOR", contador)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// Si existe savedInstanceState, la Activity se está recreando
savedInstanceState?.let {
binding.etNombre.setText(it.getString("TEXTO_USUARIO"))
contador = it.getInt("CONTADOR")
}
}
La solución moderna: ViewModel
Para datos más complejos, la solución moderna es el ViewModel. Un ViewModel sobrevive a las recreaciones de la Activity (rotaciones, cambios de configuración) y limpia sus recursos cuando la Activity se destruye definitivamente.
// ViewModel
class MainViewModel : ViewModel() {
var contador = 0
var nombre = ""
}
// Activity
class MainActivity : AppCompatActivity() {
// viewModels() crea el ViewModel y lo reutiliza si ya existe
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// viewModel.contador persiste aunque rotes el dispositivo
}
}
Regla prácticaUsá savedInstanceState para estado de UI pequeño (texto en un campo, posición de scroll). Usá ViewModel para datos de la pantalla (resultados de una llamada a la API, lista de items).