Sumérgete en Jetpack Compose

Hola a todos Antes de partir para el fin de semana, nos apresuramos a compartir con ustedes otra traducción preparada especialmente para los estudiantes del desarrollador de Android. Curso avanzado " .



Probar un nuevo marco de IU para aplicaciones de Android


En los últimos años, al participar en muchos proyectos móviles, tuve que usar varias tecnologías, como Android, ReactNative y Flutter. Cambiar de ReactNative a Android clásico me hizo sentir sentimientos encontrados. El regreso a Kotlin fue bien, pero realmente extrañé el marco React UI. Los pequeños componentes reutilizables que conforman la interfaz de usuario son excelentes y proporcionan más flexibilidad y velocidad de desarrollo.

De vuelta en Android clásico, tenía que preocuparme por mantener la jerarquía de vistas lo más uniforme posible. Debido a esto, es difícil dedicarse verdaderamente al enfoque de componentes. Esto hace que copiar y pegar sea más atractivo, lo que conduce a un código más complejo y menos compatible. En última instancia, evitamos experimentar con una interfaz de usuario que pueda mejorar UX.


Android revela Jetpack Compose. Ilustración: Emanuel Bagilla

Jetpack Componer al rescate


Por lo tanto, después de ver Novedades en Android de la conferencia Google I / O 2019, inmediatamente comencé a tratar con Compose e intenté aprender más sobre ello. Compose es un kit de herramientas de interfaz de usuario reactivo completamente desarrollado por Kotlin. Compose se parece mucho a los marcos de interfaz de usuario existentes, como React, Litho o Flutter.

La estructura actual del marco de la interfaz de usuario de Android existe desde 2008, y con el tiempo se ha vuelto más compleja, es bastante difícil de mantener. Jetpack Compose tiene como objetivo comenzar desde el principio, teniendo en cuenta la filosofía de los componentes modernos. El marco está escrito con los siguientes objetivos principales en mente:

  • Inconsistencia con las versiones de la plataforma: esto le permite corregir rápidamente los errores, ya que Compose no depende de las nuevas versiones de Android.
  • Pila de tecnología más pequeña: el marco no te obliga a usar Ver o Fragmento al crear una interfaz de usuario. Todos los elementos son componentes y se pueden componer libremente juntos.
  • Gestión de estado transparente y manejo de eventos: una de las cosas más importantes y complejas que debe resolver en aplicaciones grandes es el procesamiento del flujo de datos y el estado en su interfaz de usuario. Compose aclara quién es responsable del estado y cómo se deben manejar los eventos, de forma similar a cómo lo maneja React.
  • Escribir menos código: escribir una interfaz de usuario en Android generalmente requiere mucho código, especialmente al crear diseños más complejos, por ejemplo, usando RecyclerView. Compose tiene como objetivo simplificar enormemente la forma de crear una interfaz de usuario.

Esto facilita la creación de componentes aislados y reutilizables, lo que facilita la creación de una nueva pantalla con elementos existentes. Ayudándote, como desarrollador, a concentrarte en crear una interfaz de usuario conveniente, en lugar de tratar de controlar la jerarquía de Vista y domesticar Vista y Fragmento.

Una aplicación simple con Compose: Hello World


Echemos un vistazo al código para una sencilla aplicación Hello World con Jetpack Compose.

class ComposeActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper { MyApp() } } } @Composable fun MyApp() { MaterialTheme { Text(text = "Hello world!", style = +themeTextStyle { h3 }) } } } 

En el método onCreate establecemos el contenido de nuestra aplicación llamando a setContent . Este es un método que inicializa un árbol de widgets compuestos y lo envuelve en un FrameLayout .

Para que funcione, necesitamos envolver nuestra aplicación en CraneWrapper y MaterialTheme . CraneWrapper es responsable de configurar proveedores para Context , FocusManager y TextInputService . MaterialTheme necesario para proporcionar los colores, estilos y fuentes de sus widgets. Con esto en mente, podemos agregar el componente Text , que mostrará nuestro texto en la pantalla con cierto estilo.

Introducción del estado


Administrar el flujo de datos y los estados puede ser una tarea desalentadora. Para ilustrar lo fácil que es componer, creemos una aplicación de contador simple.
Para trabajar con estados, Jetpack Compose utiliza las ideas de otros marcos de interfaz de usuario modernos, como Flutter y React. Hay una secuencia de datos unidireccional y reactiva que hace que su widget se actualice o "reconstruya".

 @Composable fun MyApp() { MaterialTheme { Counter() } } @Composable fun Counter() { val amount = +state { 0 } Column { Text(text = "Counter demo") Button(text = "Add", onClick = { amount.value++ }) Button(text = "Subtract", onClick = { amount.value-- }) Text(text = "Clicks: ${amount.value}") } } 


En el ejemplo anterior, agregamos los botones "Agregar" y "Restar" junto con una etiqueta que muestra el número actual de clics. Como puede ver en el ejemplo a continuación, actualizando el estado de "cantidad", los widgets se reorganizan de manera inteligente cuando cambia el estado.


Lanzar una aplicación de demostración

El estado de la amount se inicializa con +state { 0 } . Tratando de descubrir qué tipo de brujería es, me metí en el código fuente. Esta es mi opinión, aunque todavía no estoy seguro de entender completamente todo.

state {...} crea un Effect< State < T < code>> . La clase Effect es una clase difusa que contiene un bloque de código ejecutable que se ejecuta posicionalmente en el contexto de una composición. La clase State contiene un valor con el tipo Model , esencialmente haciendo que este valor sea observable. El operador + es un operador temporal que resuelve el State del Effect .

Modelos de estado personalizados


En lugar de usar +state {} para crear un modelo de valor único, también podemos crear un modelo personalizado utilizando la anotación @Model. Podemos mejorar nuestra aplicación de contador dividiéndola en widgets más pequeños y pasando el modelo a otros widgets que se actualizan y muestran el estado de este modelo.

 @Model class CounterModel { var counter: Int = 0 var header = "Counter demo" fun add() { counter++ } fun subtract() { counter-- } } 


Usando la anotación @Model , el complemento Compilador de compilación hace que todas las variables en su modelo sean observables para que puedan usarse para reorganizar widgets. CounterModel nuestro widget para usar CounterModel :

 @Composable fun Counter(counterModel: CounterModel) { Column { CounterHeader(counterModel) AddSubtractButtons(counterModel) CounterLabel(counterModel) } } @Composable fun CounterHeader(counterModel: CounterModel) { Text(text = counterModel.header) } @Composable fun AddSubtractButtons(counterModel: CounterModel) { Button( text = "Add", onClick = { counterModel.add() }) Button( text = "Subtract", onClick = { counterModel.subtract() }) } @Composable fun CounterLabel(counterModel: CounterModel) { Text(text = "Clicks: ${counterModel.counter}") } 


El único widget en el que consiste la aplicación giratoria ahora está dividido en varios widgets compostables más pequeños. CounterModel se pasa a varios widgets, ya sea para mostrar el estado del modelo o para cambiar el estado del modelo utilizando las funciones add() o subtract() .

No más vista


Es importante entender que los widgets de Jetpack Compose no usan ver o fragmentar debajo del capó, estas son solo las funciones que se dibujan en el lienzo. El complemento Compose Compiler procesa todas las funciones con la anotación @Composable y actualiza automáticamente la jerarquía de la interfaz de usuario.

Por ejemplo, un widget Divider consiste en un widget Padding que contiene un widget DrawFillRect . Mirando el código fuente de DrawFillRect , queda claro que dibuja líneas directamente en el lienzo. Todos los demás widgets se implementan de la misma manera.

 @Composable private fun DrawFillRect(brush: Brush) { Draw { canvas, parentSize -> val paint = Paint() brush.applyBrush(paint) canvas.drawRect(parentSize.toRect(), paint) } } 


El código fuente para DrawFillRect que se usa dentro del widget Divider.
Si observamos el Inspector de diseño al iniciar una de las aplicaciones de muestra de Google, veremos claramente que al iniciar la aplicación de Android con Compose no hay View ni ViewGroups . Vemos un FrameLayout contiene el CraneWrapper que creamos en el código, desde allí se muestra la jerarquía de composición de la interfaz de usuario en la pantalla.


El inspector de diseño inspecciona Jetpack Compose.

La ausencia de vistas también significa que Jetpack Compose no puede usar vistas disponibles actualmente, como android.widget.Button , y debe crear todos los widgets desde cero. Si observa, por ejemplo, a Flutter, que utiliza el mismo enfoque, puede ver que se trata de un trabajo duro. Esta es una de las razones por las cuales Jetpack Compose necesitará tiempo antes de que esté listo para su uso en producción.

Todos los elementos son widgets.


Al igual que Flutter, en Compose todos los elementos son widgets. Los widgets más complejos se dividieron en widgets elementales con responsabilidades claras. Por lo tanto, incluso el relleno, los espaciadores, etc., son widgets. Por ejemplo, si desea agregar sangría alrededor de un botón, simplemente envuélvalo en el widget de relleno:

 Padding(padding = 16.dp) { Button(text = "Say hello", onClick = { ... }) } 


Código de conexión a la interfaz de usuario


Combinar el código de Kotlin con los widgets de la interfaz de usuario es muy fácil. Por ejemplo, si desea mostrar una interfaz de usuario que se repite o depende de algunas condiciones. Por lo tanto, puede mostrar fácilmente una lista de nombres, como se muestra a continuación.

 Column { listOf("John", "Julia", "Alice", "Mark").forEach { Text(text = it) } } 


Esta es una característica realmente poderosa, pero debe tener cuidado de no programar demasiada lógica en el nivel de la interfaz de usuario.

Compatible con tus aplicaciones de Android


Compose está diseñado para que pueda agregarlo a una aplicación existente y transferir gradualmente algunas partes de su IU a un nuevo marco. Los ejemplos anteriores agregan la interfaz de usuario de Jetpack Compose a una actividad. También puede incrustar widgets Compose en un diseño XML existente utilizando la anotación GenerateView :

 @Composable @GenerateView fun Greeting(name: String) { /* … */ } //  -  layout.xml <GreetingView app:name=”John” /> 

Conclusión


Estoy encantado con Compose, porque reduce el creciente sufrimiento que experimento al desarrollar para Android. Ayuda a ser más flexible, enfocarse en crear una interfaz de usuario conveniente, y una responsabilidad clara también ayuda a evitar errores.

Compose tiene un largo camino por recorrer, en mi opinión, puede usarse en la producción no antes de un año o dos. Sin embargo, creo que este es un buen momento para echar un vistazo a Jetpack Compose. Los creadores están buscando activamente comentarios, en esta etapa todavía puedes hacer cambios. Todas las revisiones ayudarán a mejorar este nuevo marco.

Lea mi artículo Try Jetpack Compose today para aprender cómo conectar Compose pre-alpha. Además, creo que será muy interesante para usted ver un video sobre plantillas de interfaz declarativas con Google I / O.
¡Espero poder usar Compose en aplicaciones reales de Android!

Eso es todo ¡Esperamos sus comentarios y que tengan un gran fin de semana!

Source: https://habr.com/ru/post/458106/


All Articles