Está en la página 1de 2

Plataforma Android 

Studio Google Play Jetpack Más ' ( Buscar Language Acceder

En esta página

Caso de éxito básico


Desarrolladores de Android ¿Te resultó útil?
Arquitectura de la capa de
la IU

Capa de la IU $
Cómo de4nir el estado de
la IU

Inmutabilidad
La función de la IU es mostrar los datos de la aplicación en la pantalla y servir como punto principal de interacción con
Convenciones de
el usuario. Cuando los datos cambian, ya sea debido a la interacción del usuario (como cuando presiona un botón) o nombres en esta guía
una entrada externa (como una respuesta de red), la IU debe actualizarse para re;ejar los cambios. En efecto, la IU es
Cómo administrar el
una representación visual del estado de la aplicación tal como se recuperó de la capa de datos. estado con un ;ujo
unidireccional de datos
Sin embargo, los datos de aplicación que obtienes de la capa de datos suelen estar en un formato diferente al de la
Contenedores de
información que necesitas mostrar. Por ejemplo, es posible que solo necesites parte de los datos de la IU, o bien que estado
debas combinar dos fuentes de datos diferentes a 4n de presentar información relevante para el usuario. Sin importar la
Tipos de lógica
lógica que apliques, debes pasarle a la IU toda la información que necesita para renderizarse por completo. La capa de
IU es la canalización que convierte los cambios en los datos de la aplicación en un formato que la IU puede presentar y, ¿Por qué usar el ;ujo
unidireccional de
luego, mostrar. datos?

Cómo exponer el estado


de la IU

Consideraciones
adicionales

Cómo consumir el estado


de la IU

Cómo mostrar las


operaciones en curso

Figura 1: La función de la capa de la IU en la arquitectura de la app

! Nota: Las recomendaciones y las prácticas recomendadas de esta página se pueden aplicar a un amplio espectro de apps
para escalarlas, mejorar su calidad y solidez, y facilitar las pruebas. Sin embargo, debes tratarlas como lineamientos y
adaptarlas a tus requisitos según sea necesario.

Caso de éxito básico


Piensa en una app que recupera artículos de noticias para que los lea un usuario. La app tiene una pantalla que presenta
los artículos que están disponibles para leer y también les permite a los usuarios que accedan marcar como favoritos
los que más les interesan. Por otro lado, como puede haber muchos artículos en cualquier momento, el lector debe ser
capaz de explorar por categoría. En resumen, la app les permite a los usuarios hacer lo siguiente:

Ver artículos disponibles para leer

Explorar artículos por categoría

Acceder y marcar artículos como favoritos

Acceder a algunas funciones premium si cumplen con los requisitos correspondientes

Figura 2: Una aplicación de noticias de muestra para un caso de éxito de la IU

En las siguientes secciones, se usa este ejemplo como caso de éxito en el que se presentan los principios del ;ujo
unidireccional de datos y se ilustran los problemas que estos principios ayudan a resolver en el contexto de la
arquitectura de la app para la capa de la IU.

Arquitectura de la capa de la IU
El término IU hace referencia a los elementos de la IU, como las actividades y los fragmentos que muestran los datos,
independientemente de las API que usen en sus tareas (vistas o Jetpack Compose). Debido a que la función de la capa
de datos es retener, administrar y proporcionar acceso a los datos de la app, la capa de la IU debe realizar los siguientes
pasos:

1. Consumir los datos de la app y transformarlos en datos que la IU pueda renderizar con facilidad

2. Consumir los datos que se pueden renderizar en la IU y transformarlos en elementos de la IU para presentarlos al
usuario

3. Consumir eventos de entrada del usuario a partir de esos elementos de la IU ensamblados y re;ejar sus efectos en
los datos de la IU según sea necesario

4. Repetir los pasos 1 al 3 durante el tiempo que sea necesario

En el resto de esta guía, se muestra cómo implementar una capa de IU que realice estos pasos. En particular, en esta
guía, se abarcan las siguientes tareas y conceptos:

Cómo de4nir el estado de la IU

El ;ujo unidireccional de datos como medio para producir y administrar el estado de la IU

Cómo exponer el estado de la IU con tipos de datos observables según los principios del ;ujo unidireccional de
datos

Cómo implementar una IU que consuma su estado observable

El más importante de todos es la de4nición del estado de la IU.

Cómo definir el estado de la IU


Consulta el caso de éxito que se describió anteriormente. En resumen, la IU muestra una lista de artículos junto con
algunos metadatos para cada uno. Esta información que la app presenta al usuario es el estado de la IU.

En otras palabras, si la IU es lo que ve el usuario, el estado de la IU es lo que la app dice que debería ver. Al igual que dos
caras de una moneda, la IU es la representación visual del estado de la IU. Cualquier cambio en el estado de la IU se
re;eja de inmediato en la IU.

Figura 3: La IU es el resultado de la vinculación de sus elementos en la pantalla con el estado correspondiente.

Considera este caso de éxito: A 4n de cumplir con los requisitos de la app de Noticias, la información necesaria para
renderizar por completo la IU se puede encapsular en una clase de datos NewsUiState de4nida de la siguiente manera:

%&
data class NewsUiState(
    val isSignedIn: Boolean = false,
    val isPremium: Boolean = false,
    val newsItems: List<NewsItemUiState> = listOf(),
    val userMessages: List<Message> = listOf()
)

data class NewsItemUiState(


    val title: String,
    val body: String,
    val bookmarked: Boolean = false,
    ...
)

Inmutabilidad

La de4nición del estado de la IU en el ejemplo anterior es inmutable. El bene4cio clave de esto es que los objetos
inmutables proporcionan garantías sobre el estado de la aplicación en un momento determinado. De esta manera, se
libera la IU para enfocarse en una sola función: leer el estado y actualizar sus elementos según corresponda. Como
resultado, nunca debes modi4car el estado de la IU directamente en la IU, a menos que la IU sea la única fuente de
datos. Infringir este principio genera varias fuentes verídicas para la misma información, lo que genera inconsistencias
en los datos y errores leves.

Por ejemplo, si la marca bookmarked en un objeto NewsItemUiState del estado de la IU en el caso de éxito se
actualiza en la clase Activity , esa marca competiría con la capa de datos como fuente del estado "agregado a
favoritos" de un artículo. Las clases de datos inmutables son muy útiles para evitar este tipo de antipatrón.

" Punto clave: Solo las fuentes o los propietarios de los datos deben ser responsables de actualizar los datos que exponen.

Convenciones de nombres en esta guía

En esta guía, las clases de estado de la IU se nombran según la funcionalidad de la pantalla o parte de la pantalla que
describen. La convención es la siguiente:

funcionalidad + UiState

Por ejemplo, el estado de una pantalla que muestra noticias podría llamarse NewsUiState , y el estado de un elemento
de noticias en una lista de noticias podría ser NewsItemUiState .

Cómo administrar el estado con un flujo unidireccional de datos


En la sección anterior, se estableció que el estado de la IU es un resumen inmutable de los detalles necesarios para la
renderización de la IU. Sin embargo, debido a la naturaleza dinámica de los datos en las apps, el estado puede cambiar
con el tiempo. Esto podría deberse a la interacción del usuario o a otros eventos que modi4quen los datos subyacentes
que se usan para propagar la app.

Estas interacciones pueden bene4ciarse de un mediador para procesarlas, de4nir la lógica que se aplicará a cada evento
y realizar las transformaciones necesarias en las fuentes de datos de respaldo a 4n de crear el estado de la IU. Estas
interacciones y su lógica pueden estar alojadas en la IU, pero podrían volverse difíciles de controlar cuando la IU
comienza a ser más de lo que su nombre sugiere: se convierte en propietario, productor, transformador y mucho más.
Además, esto puede afectar la capacidad de prueba porque el código resultante es una amalgama de acoplamiento alto
y sin límites discernibles. En última instancia, la IU se bene4cia de una reducción de carga. A menos que el estado de la
IU sea muy simple, la única responsabilidad de la IU será el consumo y la visualización del estado de la IU.

En esta sección, se analiza el ;ujo unidireccional de datos, un patrón de arquitectura que ayuda a aplicar esta
separación saludable de responsabilidades.

Contenedores de estado

Las clases que son responsables de la producción del estado de la IU y contienen la lógica necesaria para esa tarea se
denominan contenedores de estado. Los contenedores de estado están disponibles en una variedad de tamaños, según
el alcance de los elementos correspondientes de la IU que administran, lo que comprende desde un solo widget, como
una barra inferior de la app, hasta una pantalla completa.

En el último caso, la implementación típica es una instancia de un ViewModel, aunque, según los requisitos de la
aplicación, una clase simple puede ser su4ciente. La app de Noticias del caso de éxito, por ejemplo, usa una clase
NewsViewModel como contenedor de estado para producir el estado de la IU de la pantalla que se muestra en esa
sección.

" Punto clave: El tipo ViewModel es la implementación recomendada para administrar el estado de la IU a nivel de pantalla
con acceso a la capa de datos. Además, sobrevive automáticamente a los cambios de con4guración. Las clases
ViewModel de4nen la lógica que se aplica a los eventos en la app y, como resultado, producen un estado actualizado.

Hay muchas maneras de modelar la codependencia entre la IU y su productor de estado. Sin embargo, debido a que la
interacción entre la IU y su clase ViewModel se puede comprender en gran medida como una entrada de evento y su
resultado de estado posterior, la relación se pueden representar como se muestra en el siguiente diagrama:

Figura 4: Diagrama de cómo funciona el ;ujo unidireccional de datos en la arquitectura de la app

El patrón en el que el estado ;uye hacia abajo y los eventos ;uyen hacia arriba se denomina ;ujo unidireccional de
datos. Las implicaciones de este patrón para la arquitectura de la app son las siguientes:

ViewModel conserva y expone el estado que consumirá la IU. El estado de la IU son los datos de aplicación que
transforma ViewModel.

La IU noti4ca al ViewModel los eventos de usuario.

ViewModel controla las acciones del usuario y actualiza el estado.

El estado actualizado se envía a la IU para su renderización.

El proceso anterior se repite para cualquier evento que cause una mutación del estado.

Para pantallas o destinos de navegación, ViewModel funciona con repositorios o clases de caso de uso a 4n de obtener
datos y transformarlos en el estado de la IU, a la vez que incorpora los efectos de los eventos que pueden causar
mutaciones del estado. El caso de éxito mencionado anteriormente contiene una lista de artículos, cada uno con un
título, una descripción, una fuente, un nombre de autor, la fecha de publicación y si se agregó a favoritos. La IU de cada
elemento de artículo se ve así:

Figura 5: IU de un elemento de artículo en la app del caso de éxito

Un usuario que solicita agregar un artículo a favoritos es un ejemplo de un evento que puede generar mutaciones del
estado. Como productor de estado, la responsabilidad de ViewModel es de4nir toda la lógica necesaria para propagar
todos los campos en el estado de la IU y procesar los eventos necesarios a 4n de que la IU se renderice por completo.

Figura 6: Diagrama que ilustra el ciclo de eventos y datos en el ;ujo unidireccional de datos

En las siguientes secciones, se analizan con más detalle los eventos que causan cambios de estado y cómo se pueden
procesar mediante un ;ujo unidireccional de datos.

Tipos de lógica

Agregar un artículo a favoritos es un ejemplo de lógica empresarial porque aporta valor a tu app. Para obtener más
información, consulta la página sobre capa de datos. Sin embargo, hay distintos tipos de lógica que es importantes
de4nir:

La lógica empresarial hace referencia a qué hacer con los cambios de estado. Como ya se mencionó, un ejemplo
es agregar a favoritos un artículo en la app del caso de éxito. Por lo general, la lógica empresarial se ubica en las
capas de dominio o datos, pero nunca en la capa de la IU.

La lógica de comportamiento de la IU o lógica de la IU es cómo se muestran los cambios de estado en la pantalla.


Algunos ejemplos incluyen obtener el texto adecuado para mostrar en la pantalla con Android Resources ,
navegar a una pantalla en particular cuando el usuario hace clic en un botón o mostrar un mensaje en pantalla
mediante un aviso o una barra de noti4caciones.

La lógica de la IU, en especial cuando implica tipos de IU como Context , debería encontrarse en la IU, no en
ViewModel. Si la IU aumenta su complejidad y deseas delegar su lógica a otra clase para favorecer la capacidad de
prueba y la separación de los problemas, puedes crear una clase simple como contenedor de estado. Las clases
simples creadas en la IU pueden tomar dependencias del SDK de Android porque siguen el ciclo de vida de la IU; los
objetos ViewModel tienen una vida útil más larga.

Para obtener más información sobre los contenedores de estado y cómo se ajustan al contexto de la ayuda de la IU de
compilación, consulta la Guía de estado de Jetpack Compose.

¿Por qué usar el flujo unidireccional de datos?

El ;ujo unidireccional de datos modela el ciclo de producción del estado, como se muestra en la Figura 4. También
separa el lugar donde se originan los cambios de estado, el lugar en el que se transforman y el lugar donde se
consumen. Esta separación permite que la IU haga exactamente lo que su nombre implica: mostrar información
mediante la observación de cambios de estado y retransmitir la intención del usuario pasando esos cambios al
ViewModel.

En otras palabras, el ;ujo unidireccional de datos permite lo siguiente:

Coherencia de los datos. Hay una sola fuente de información para la IU.

Capacidad de realizar pruebas. Como la fuente de estado está aislada, se puede probar de forma independiente
de la IU.

Capacidad de mantenimiento. La mutación del estado sigue un patrón bien de4nido en el que las mutaciones son
el resultado de los eventos de un usuario y las fuentes de datos con las que trabajan.

Cómo exponer el estado de la IU


Después de de4nir el estado de tu IU y determinar cómo administrarás la producción de ese estado, el siguiente paso es
presentar el estado producido en la IU. Como usarás un ;ujo unidireccional de datos para administrar la producción del
estado, puedes considerar que el estado producido es una transmisión, es decir, se generarán varias versiones del
estado a lo largo del tiempo. Como resultado, debes exponer el estado de la IU en un contenedor de datos observable,
como LiveData o StateFlow . La idea es que la IU puede reaccionar a cualquier cambio realizado en el estado sin
tener que extraer manualmente los datos directamente desde ViewModel. Estos tipos también tienen el bene4cio de
tener siempre la versión más reciente del estado de la IU almacenada en caché, lo cual es útil para realizar un
restablecimiento rápido del estado después de cambios de con4guración.

Vistas Compose

%&
class NewsViewModel(...) : ViewModel() {

    val uiState: StateFlow<NewsUiState> = …


}

Para ver una introducción a LiveData como contenedor de datos observable, consulta este codelab. También puedes
ver una introducción similar a los ;ujos de Kotlin en Flujos de Kotlin en Android.

! Nota: En las apps de Jetpack Compose, puedes usar el método observable de Compose.API de estado
comomutableStateOf osnapshotFlow para la exposición del estado de la IU. Cualquier tipo de contenedor de datos
observables, como StateFlow o LiveData, que puedes ver en esta guía, puede consumirse con facilidad en Compose con
las extensiones adecuadas.

Cuando los datos expuestos a la IU son relativamente simples, vale la pena unirlos en un tipo de estado de IU porque así
se transmite la relación entre la emisión del contenedor de estado y su pantalla o elemento de la IU asociados. Además,
a medida que el elemento de la IU se vuelve más complejo, siempre es más fácil agregarlo a la de4nición del estado de
la IU para adaptarlo a la información adicional necesaria para procesar ese elemento.

Una forma común de crear una transmisión de UiState es exponer una transmisión mutable de respaldo como una
transmisión inmutable desde ViewModel, por ejemplo, exponer una MutableStateFlow<UiState> como
StateFlow<UiState> .

Vistas Compose

%&
class NewsViewModel(...) : ViewModel() {

    private val _uiState = MutableStateFlow(NewsUiState())


    val uiState: StateFlow<NewsUiState> = _uiState.asStateFlow()

    ...

ViewModel puede exponer los métodos que mutan de forma interna el estado, lo que publica actualizaciones para que
consuma la IU. Tomemos, por ejemplo, el caso en el que se debe realizar una acción asíncrona: se puede iniciar una
corrutina mediante el viewModelScope y el estado mutable se puede actualizar después de su 4nalización.

Vistas Compose

%&
class NewsViewModel(
    private val repository: NewsRepository,
    ...
) : ViewModel() {

    private val _uiState = MutableStateFlow(NewsUiState())


    val uiState: StateFlow<NewsUiState> = _uiState.asStateFlow()

    private var fetchJob: Job? = null

    fun fetchArticles(category: String) {


        fetchJob?.cancel()
        fetchJob = viewModelScope.launch {
            try {
                val newsItems = repository.newsItemsForCategory(category)
                _uiState.update {
                    it.copy(newsItems = newsItems)
                }
            } catch (ioe: IOException) {
                // Handle the error and notify the UI when appropriate.
                _uiState.update {
                    val messages = getMessagesFromThrowable(ioe)
                    it.copy(userMessages = messages)
                 }
            }
        }
    }
}

En el ejemplo anterior, la clase NewsViewModel intenta recuperar artículos para una categoría determinada y, luego,
re;eja el resultado del intento (ya sea éxito o error) en el estado de la IU, en el que la IU puede reaccionar de forma
adecuada. Consulta la sección Mostrar errores en la pantalla para obtener más información sobre la resolución de
errores.

! Nota: El patrón que se muestra en el ejemplo anterior, en el que el estado muta mediante las funciones del ViewModel, es
una de las implementaciones más populares del ;ujo unidireccional de datos.

Consideraciones adicionales

Además de la guía anterior, ten en cuenta lo siguiente cuando expongas el estado de la IU:

Un objeto de estado de la IU debería controlar los estados relacionados entre sí. Esta implementación genera
menos inconsistencias y facilita la comprensión del código. Si expones la lista de elementos de noticias y la
cantidad de favoritos en dos transmisiones diferentes, podrías terminar en una situación en la que una se
actualice y la otra no. Si usas una sola transmisión, todos los elementos se mantendrán actualizados. Además,
parte de la lógica empresarial podría requerir una combinación de fuentes. Por ejemplo, es posible que debas
mostrar un botón de favoritos solo si el usuario accede a su cuenta y está suscrito a un servicio de noticias
premium. Podrías de4nir una clase de estado de IU de la siguiente manera:

%&
data class NewsUiState(
    val isSignedIn: Boolean = false,
    val isPremium: Boolean = false,
    val newsItems: List<NewsItemUiState> = listOf()
)

val NewsUiState.canBookmarkNews: Boolean get() = isSignedIn && isPremium

En esta declaración, la visibilidad del botón de favoritos es una propiedad derivada de otras dos. A medida que la
lógica empresarial se vuelve más compleja, tener una clase UiState singular en la que todas las propiedades
estén disponibles de inmediato se vuelve cada vez más importante.

Estados de la IU: ¿una o varias transmisiones? El principio guía clave para elegir entre exponer el estado de la IU
en una sola o en varias transmisiones es la viñeta anterior: la relación entre los elementos emitidos. La mayor
ventaja de una exposición de una sola transmisión es la comodidad y la coherencia de los datos: los
consumidores de estado siempre tienen la información más reciente disponible en cualquier momento. Sin
embargo, hay instancias en las que tener transmisiones de estado separadas del ViewModel podría ser apropiado:

Tipos de datos no relacionados: Algunos estados necesarios para procesar la IU podrían ser completamente
independientes entre sí. En casos como estos, los costos de agrupar estos estados dispares podrían superar
los bene4cios, en especial si uno de estos estados se actualiza con más frecuencia que otro.

DiMng de UiState : Cuantos más campos haya en un objeto UiState , más probable será que la
transmisión emita contenido como resultado de la actualización en uno de sus campos. Debido a que las
vistas no tienen un mecanismo de difng para comprender si las emisiones consecutivas son diferentes o
iguales, cada emisión genera una actualización para la vista. Por lo tanto, podría requerirse una mitigación
con las API o los métodos de Flow , como distinctUntilChanged() # en LiveData .

Cómo consumir el estado de la IU


A 4n de consumir el ;ujo de objetos UiState en la IU, aplica el operador de terminal para el tipo de datos observable
que usas. Por ejemplo, para LiveData , usa el método observe() , y para ;ujos de Kotlin, usa el método collect() o
sus variantes.

Cuando uses contenedores de datos observables en la IU, asegúrate de tener en cuenta el ciclo de vida de la IU. Esto es
importante porque la IU no debería observar su estado cuando la vista no se le muestra al usuario. Para obtener más
información sobre este tema, consulta esta entrada de blog #. Cuando usas LiveData , LifecycleOwner se encarga
de forma implícita de los asuntos del ciclo de vida. Cuando se usan ;ujos, es mejor controlarlos con el permiso de
corrutina correcto y la API de repeatOnLifecycle :

Vistas Compose

%&
class NewsActivity : AppCompatActivity() {

    private val viewModel: NewsViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {


        ...

        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.uiState.collect {
                    // Update UI elements
                }
            }
        }
    }
}

! Nota: Los objetos StateFlow especí4cos que se usan en este ejemplo no dejan trabajar cuando no tienen recopiladores
activos. Sin embargo, cuando trabajas con ;ujos, es posible que no sepas cómo se implementan. Usar la recopilación de
;ujos optimizados para ciclos de vida te permite realizar este tipo de cambios en los ;ujos del ViewModel más adelante sin
volver a revisar el código recopilador descendente.

Cómo mostrar las operaciones en curso

Una forma sencilla de representar estados de carga en una clase UiState es con un campo booleano:

%&
data class NewsUiState(
    val isFetchingArticles: Boolean = false,
    ...
)

El valor de esta marca representa la presencia o ausencia de una barra de progreso en la IU.

Vistas Compose

%&
class NewsActivity : AppCompatActivity() {

    private val viewModel: NewsViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {


        ...

        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                // Bind the visibility of the progressBar to the state
                // of isFetchingArticles.
                viewModel.uiState
                    .map { it.isFetchingArticles }
                    .distinctUntilChanged()
                    .collect { progressBar.isVisible = it }
            }
        }
    }
}

Cómo mostrar errores en la pantalla

Mostrar errores en la IU es similar a mostrar operaciones en curso porque ambos se representan fácilmente con valores
booleanos que denotan su presencia o ausencia. Sin embargo, los errores también pueden incluir un mensaje asociado
para retransmitir al usuario, o bien para una acción asociada con ellos que reintente la operación fallida. Por lo tanto,
mientras una operación en curso se carga o no, es posible que los estados de error necesiten modelarse con clases de
datos que alojen los metadatos adecuados para el contexto de ese error.

Por ejemplo, considera el ejemplo de la sección anterior que mostraba una barra de progreso mientras se recuperaban
los artículos. Si esta operación da como resultado un error, es posible que quieras mostrar uno o más mensajes al
usuario en los que se detalle lo que salió mal.

%&
data class Message(val id: Long, val message: String)

data class NewsUiState(


    val userMessages: List<Message> = listOf(),
    ...
)

Los mensajes de error se pueden presentar al usuario en forma de elementos de la IU, como barras de noti4caciones. Y
como esto se relaciona con la manera en que se producen y consumen los eventos de la IU, consulta la página Eventos
de la IU para obtener más información.

Subprocesos y simultaneidad
Cualquier trabajo que se realice en un ViewModel debe ser seguro para llamar desde el subproceso principal. Esto se
debe a que las capas de datos y dominio son responsables de mover el trabajo a un subproceso diferente.

Si un ViewModel realiza operaciones de larga duración, también es responsable de mover esa lógica a un subproceso en
segundo plano. Las corrutinas de Kotlin son una excelente manera de administrar operaciones simultáneas, y los
componentes de la arquitectura de Jetpack proporcionan compatibilidad integrada. Para obtener más información
sobre el uso de corrutinas en apps para Android, consulta Corrutinas de Kotlin en Android.

Navigation
Los cambios en la navegación de las apps suelen deberse a las emisiones que parecen eventos. Por ejemplo, después
de que una clase SignInViewModel realiza un acceso, el UiState puede tener un campo isSignedIn establecido en
true . Estos activadores deben consumirse tal como los que se abordan en la sección Cómo consumir el estado de la
IU anterior, excepto que la implementación del consumo debe remitirse al componente Navigation.

Paging
La biblioteca de Paging se consume en la IU con un tipo llamado PagingData . Debido a que PagingData representa y
contiene elementos que pueden cambiar con el tiempo (es decir, no es un tipo inmutable), no debe representarse en un
estado de IU inmutable. En cambio, debes exponer estos datos desde el ViewModel de forma independiente en su
propia transmisión. Consulta el codelab Android Paging para ver un ejemplo especí4co.

Animaciones
Para proporcionar transiciones de navegación de primer nivel y que se vean ;uidas, puedes esperar a que la segunda
pantalla cargue los datos antes de iniciar la animación. El framework de vista de Android proporciona hooks para
retrasar las transiciones entre destinos de fragmentos con las API de postponeEnterTransition()
y startPostponedEnterTransition() . Estas API garantizan que los elementos de la IU de la segunda pantalla (por lo
general, una imagen recuperada de la red) estén listos para mostrarse antes de que la IU anime la transición a esa
pantalla. Para obtener más detalles e información especí4ca de implementación, consulta la muestra de Android
Motion #.
¿Te resultó útil?

Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks
of Oracle and/or its afliates.

Last updated 2022-01-30 UTC.

Twitter YouTube LinkedIn


Sigue a @AndroidDev Busca Android Developers en Conectarse con la comunidad
en Twitter YouTube de desarrolladores de Android
en LinkedIn

M ÁS A N D RO I D DESCUBRE D I S P O S I T I VO S A N D RO I D VERSIONES D O C U M E N TAC I Ó N Y AS I ST E N C I A


D E S CA RG AS
Android Videojuegos Pantallas grandes Android 11 Informar sobre un error en la
Guía de Android Studio plataforma
Android para empresas Aprendizaje automático Wear OS Android 10
Guías para desarrolladores Informar sobre un error en la
Seguridad Privacidad Android TV Pie documentación
Referencia de API
Código abierto 5G Android para vehículos Oreo Google Play support
Descargar Studio
Noticias Android Things Nougat Participar en los estudios de
NDK de Android investigación
Blog Dispositivos con Chrome OS Marshmallow

Podcasts Lollipop

KitKat

Android Chrome Firebase Google Cloud Platform Todos los productos

Privacidad | Licencia | Lineamientos de marca Recibe noticias y sugerencias por correo electrónico Suscribirse Language

También podría gustarte