Actualmente estoy estudiando Jetpack Compose en un intento de crear una aplicación rica en funciones utilizando componentes modernos de la arquitectura de Android. Tradicionalmente, cada pantalla (o unidad de navegación) en mi aplicación sería una actividad o un fragmento, cada uno con sus propios enlaces de ciclo de vida, pero con Jetpack Compose y la biblioteca Compose Navigation, haría algo como esto:
MainActivity.kt
:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "main") {
composable("main") { MainScreen(navController) }
// More composable calls
}
}
}
}
Donde MainScreen
es solo un componible. Mis preguntas son:
- ¿Cuál es el equivalente aquí de un “ciclo de vida” para este componible? Digamos que quiero realizar alguna acción cuando se carga la pantalla, cuando se destruye, etc. Esto quizás sea más relevante para el caso en el que tengo más pantallas y navegación entre ellas.
- ¿Hay alguna forma de integrar Compose y las actividades estándar? Es decir, defina actividades para pantallas como lo haría, siendo cada actividad un
ComponentActivity
y definir su propio diseño componible? ¿Esto se desaconseja por alguna razón?
La aplicación Compose está diseñada para usarse en una arquitectura de actividad única sin fragmentos.
Todavía puede tener múltiples actividades o fragmentos y usar setContent
en cada una de ellas, pero en este caso la transferencia de datos entre actividades recae sobre tus hombros. Use este enfoque si está agregando nuevas pantallas de Redacción a una aplicación existente construida de la manera anterior.
Pero con Compose, es mucho más fácil hacer toda la navegación dentro de una sola actividad usando Compose Navigation. Mucho menos código, mejor rendimiento debido a que no hay capas de código innecesarias, fácil transferencia de datos, etc.
Para trabajar con el ciclo de vida de la vista, consulte componer efectos secundarios:
LaunchedEffect
se puede utilizar para ejecutar una acción cuando aparece la vista. También se ejecuta en un contexto de corrutina que está vinculado al componible actual: puede ejecutar fácilmente funciones de suspensión y, cuando la vista desaparezca de la jerarquía de vistas, la corrutina se cancelará.
DisposableEffect
se puede utilizar para suscribirse o darse de baja de las devoluciones de llamada.
Cuando giras la pantalla, todos los efectos se reiniciarán sin importar qué tecla hayas pasado.
@Composable
fun MainScreen(navController: NavController) {
LaunchedEffect(Unit) {
println("LaunchedEffect: entered main")
var i = 0
// Just an example of coroutines usage
// don't use this way to track screen disappearance
// DisposableEffect is better for this
try {
while (true) {
delay(1000)
println("LaunchedEffect: ${i++} sec passed")
}
} catch (cancel: CancellationException) {
println("LaunchedEffect: job cancelled")
}
}
DisposableEffect(Unit) {
println("DisposableEffect: entered main")
onDispose {
println("DisposableEffect: exited main")
}
}
}
También tenga en cuenta que en ambos casos, y en muchos otros casos en componer, pasa key
a estas funciones. Esto ayuda a componer a comprender cuándo se debe volver a calcular el valor. En mi ejemplo es Unit
, lo que significa que no cambiará hasta que desaparezca la vista. Pero si creas un remember
valor, use otro valor dinámico del modelo de vista o pase otro argumento a componible, puede pasarlo como un key
esto cancelará la actual LaunchedEffect
trabajo y llamada onDispose
por DisposableEffect
y su trabajo se reiniciará con la actualización key
valor. Puedes pasar tantas llaves como quieras.
Lea más sobre el estado en Redactar en documentación.