Slide 1

Slide 1 text

Jetpack Compose Facundo Rodríguez Arceri @facundomr

Slide 2

Slide 2 text

¿Qué es Jetpack Compose? ● Librería ● Plugin del compilador de Kotlin

Slide 3

Slide 3 text

¿Quién lo desarrolla? ● El equipo de desarrollo de Android. ● En colaboración con Jetbrains.

Slide 4

Slide 4 text

¿Por qué? ● Librerías > clases del SDK. ● Retrocompatibilidad. ● Complejidad para reutilizar Views. ● Single source of truth. ● Necesidad de minimizar el código necesario.

Slide 5

Slide 5 text

¿Por qué ahora? ● Diez años de Android ● Tendencia ● Compatibilidad con layouts existentes ● Kotlin ❤

Slide 6

Slide 6 text

¿Cómo aprender? ● Tutorial oficial ● Codelab ● Slack team: kotlinlang ● ¡Esta charla!

Slide 7

Slide 7 text

¡Empecemos!

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

Hasta ahora... ● Una Activity en Android constaba de dos partes: ○ Clase (Java/Kotlin) ○ Layout (XML)

Slide 10

Slide 10 text

Slide 11

Slide 11 text

class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } }

Slide 12

Slide 12 text

class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) greeting.text = "Hello Facu!" } }

Slide 13

Slide 13 text

Declarative UI ● Qué vs Cómo ● Separación de responsabilidades ● Cohesión vs Acoplamiento

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MaterialTheme { Greeting("Android") } } } } @Composable fun Greeting(name: String) { Text(text = "Hello $name!") }

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

@Composable ● Funciones Kotlin simples. ● La anotación hace la magia ✨ ● ¡No genera Views convencionales! ● Son reinvocadas cada vez que cambian los parámetros de entrada.

Slide 18

Slide 18 text

¿Qué puedo hacer con ellas? ● ¡Lo que quieras, es código Kotlin! ● Composición por sobre herencia

Slide 19

Slide 19 text

Composición

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

data class Player(val name: String, val number: Int) class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val players = arrayListOf( Player("Nicolas Tagliafico", 3), Player("Leandro Paredes", 5), Player("Sergio Agüero", 9), Player("Lionel Messi", 10) ) setContent { PlayersList(players) } } }

Slide 22

Slide 22 text

@Composable fun PlayersList(players: List) { Column { players.forEach { PlayerRow(it) } } }

Slide 23

Slide 23 text

@Composable fun PlayerRow(player: Player) { Padding(padding = EdgeInsets(left = 32.dp, right = 16.dp, top = 8.dp, bottom = 8.dp)) { Row { Text( text = "${player.number}", style = TextStyle(fontWeight = FontWeight.Bold) ) WidthSpacer(width = 24.dp) Text(text = player.name) } } }

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

Flujo de datos

Slide 26

Slide 26 text

Flujo de datos ● La idea es simplificar la arquitectura. ● Las @Composable reciben los objetos que dibujan. ● Los eventos que ocurren en una @Composable deben ser delegados a quien la invocó.

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

@Composable fun PlayersList(players: List) { Column { players.forEach { PlayerRow(it, listener = { Toast.makeText(baseContext, "Clickeaste a ${it.name}", Toast.LENGTH_SHORT) .show() }) } } }

Slide 29

Slide 29 text

@Composable fun PlayerRow(player: Player, listener: ((Player) -> Unit)) { Clickable(onClick = { listener(player) }) { Padding(padding = EdgeInsets(left = 32.dp, right = 16.dp, top = 8.dp, bottom = 8.dp)) { Row { Text( text = "${player.number}", style = TextStyle(fontWeight = FontWeight.bold) ) WidthSpacer(width = 24.dp) Text(text = player.name) } } } }

Slide 30

Slide 30 text

Reactividad

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

Reaccionando a cambios en el estado ● El estado de la pantalla debe ser almacenado en alguna @Composable. ● Dicho estado debe ser observable. ● Las @Composables correspondientes deben ser reinvocadas cuando algún atributo del estado cambia.

Slide 33

Slide 33 text

@Model data class MainActivityModel(var players: MutableList = mutableListOf())

Slide 34

Slide 34 text

@Model ● Genera una nueva clase. ● Atributos observables. ● Thread-safe. ● Cuando una @Composable acceda a un atributo, será reinvocada cada vez que dicho atributo cambie.

Slide 35

Slide 35 text

class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MyApp() } } }

Slide 36

Slide 36 text

@Composable fun MyApp(model: MainActivityModel = MainActivityModel()) { MaterialTheme { FlexColumn { inflexible { Button(text = "Agregar jugador", onClick = { model.players.add(Player("Nuevo jugador ${model.players.size}", model.players.size)) model.players = model.players }) } flexible(flex = 1f) { PlayersList(model.players) } } } }

Slide 37

Slide 37 text

@Composable fun PlayersList(players: List) { VerticalScroller { Column { players.forEach { PlayerRow(it) } } } }

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

Repasando

Slide 40

Slide 40 text

Links útiles ● Documentación - https://d.android.com/jetpackcompose ● Codelab - https://codelabs.developers.google.com/codelabs/jetpack-compose-basics ● Android Dev Summit 2019 - https://www.youtube.com/user/androiddevelopers/playlist ● Android Devs Bs As - https://www.twitter.com/AndroidDevsBsAs

Slide 41

Slide 41 text

¿Preguntas?

Slide 42

Slide 42 text

¡Muchas gracias!