DEV Community

Cover image for Olá, Jetpack Compose
Tiago Taraczuk for Pixelwolfhq

Posted on

Olá, Jetpack Compose

Notas: Esse artigo está sendo escrito com base na versão 1.0.0-beta01 e tem como finalidade apresentar o novo sistema de UI para Android. No momento é necessário utilizar a versão canary do Android Studio para trabalhar com o Compose.

O Jetpack Compose finalmente foi liberado como beta! E agora é a melhor hora para você começar a aprender sobre o novo sistema de UI do Android.


O que é o Compose?

O Jetpack Compose é novo sistema de UI do Android, criado para substituir o atual (e já defasado) sistema de Views. Isso também faz com que o Android acompanhe as tendências de criação de UI declarativa, como ja existe com o SwiftUI, Flutter e React Native.

Algumas coisas muito legais sobre o Compose:

  • 100% Kotlin: Isso permite tirar proveito total dessa poderosa linguagem.
  • Desacoplado do sistema operacional: Isso permite que as atualizações e correções de bugs não dependam do sistema Android, e ainda possibilita usar o Compose em outras plataformas como desktop e web.

Imperativo vs Declarativo

Antes de começar a trabalhar com o Compose, é bom saber as diferenças da criação de UI Imperativa (sistema atual) e UI declarativa (Compose).

Quando utilizamos o modelo imperativo, precisamos descrever como cada elemento da tela irá funcionar. Já no modelo declarativo, nós iremos dizer o que deverá acontecer em cada estado. Eu gosto de descrever esses dois paradigmas como:

  • Imperativo = "Faça isso!"
  • Declarativo = "Seja isso."

Vamos ver um exemplo de como isso funciona.

Vamos supor que temos um TextView que mostra o saldo da conta e ele tem 2 estados.

  1. O texto deverá ser da cor verde caso o saldo seja maior ou igual a zero;
  2. O texto deverá ser da cor vermelha caso o saldo seja menor que zero.

No modelo imperativo, isso ficaria mais ou menos assim:

<TextView
      android:id="@+id/tv_balance"
      android:layout_width="match_parent"
      android:layout_height="wrap_content" />
Enter fullscreen mode Exit fullscreen mode
private fun updateBalance(balance: Double) {
      val tvBalance = findViewById<TextView>(R.id.tv_balance)
      if (balance >= 0) {
        tvBalance.setTextColor(Color.GREEN)
      } else {
        tvBalance.setTextColor(Color.RED)
      }
      tvBalance.text = "$balance"
}
Enter fullscreen mode Exit fullscreen mode

E no modelo declarativo:

@Composable
fun UserBalance(balance: Double) {
    Text(
        text = "$balance",
        color = if (balance >= 0) Color.Green else Color.Red,
    )
}
Enter fullscreen mode Exit fullscreen mode

Olhando rapidamente a primeira coisa que é possível perceber nesse cenário, é que o código está mais simples na versão declarativa. Porém, esse não é o ponto mais importante. Perceba que no modelo declarativo o componente possui o seus estados internalizados, ou seja, ele é isso. No modelo imperativo é necessário mandar a view agir de tal forma, ou seja, estamos mandando que ele faça isso.


Como criar layouts com o Compose?

Os layouts no compose são criados através de uma árvore de elementos de UI, esses elementos são chamados de composable functions.

Nós vimos um exemplo de como é uma composable function na explicação sobre o paradigma de programação declarativa, a seguir veremos alguns outros exemplos para um melhor entendimento.

Primeiro vamos ver como criar uma função para apresentar um texto.

@Composable
fun Greeting(name: String = "Tiago") {
    Text("Olá, $name!")
}
Enter fullscreen mode Exit fullscreen mode

Toda composable function deverá ser anotada com @Composable. Isso fará com que o compilador entenda que ele deverá transformar as informações de dentro da função em UI.

Nesse exemplo, foi criado uma composable function que recebe um parâmetro, esse parâmetro foi usado em outra composable function chamada Text. A função Text faz parte da biblioteca de UI do Compose e é responsável por renderizar um elemento de texto na tela.

O resultado é esse:

Text simples sem nenhum modificador apresentando o texto "Olá, Tiago!"

Os elementos respeitam a ordem que foram criados. Vamos ver um exemplo onde vários Text são apresentados na tela.

@Composable
fun Greeting(names: List<String> = listOf("Tiago", "Luiz", "Jefferson")) {
    for (name in names) {
        Text(text = "Olá, $name!")
    }
}
Enter fullscreen mode Exit fullscreen mode

Esse é o resultado:

Vários Text empilhados

Perceba que todos os Text ficaram empilhados, e isso está correto! Isso aconteceu porque não foi especificado como eles deveriam ser apresentados.

O Compose possui várias composable functions prontas, uma delas é a Column. Vamos ver um exemplo usando o Column para apresentar os Text um em baixo do outro.

@Composable
fun Greeting(names: List<String> = listOf("Tiago", "Luiz", "Jefferson")) {
    Column {
        for (name in names) {
            Text(text = "Olá, $name!")
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Fazendo um comparativo com o sistema atual, o Column é similar ao LinearLayout na orientação vertical, para orientação horizontal, o Compose disponibiliza o componente Row.

Resultado:

Column com 3 Texts

Esses são alguns exemplos bem simples mostrando como apresentar elementos estáticos, mas e se for necessário fazer alguma atualização na tela?

Toda vez que um componente tem seus dados alterados, ele passa por um processo chamado recomposition. Nesse processo o elemento é chamado novamente e o Compose é inteligente o suficiente para alterar apenas o necessário.

Vamos ver um exemplo de um Button:

@Composable
fun ClickCounterButton() {
    var numberOfClicks by remember { mutableStateOf(0) }
    Button(onClick = { numberOfClicks++ }) {
        Text(text = "Eu fui clickado $numberOfClicks vezes.")
    }
}
Enter fullscreen mode Exit fullscreen mode

Nesse caso, toda vez que o numberOfClicks for alterado, o Button passará pelo recomposition.

Resultado:

Gif mostrando a funcionalidade de um counter


Próximos passos

O propósito desse artigo foi apenas apresentar o novo sistema de UI do Android, ainda temos muitos conteúdos para ver, como: configuração de um projeto, states, modifiers, themes, layouts, etc.

Esse artigo fará parte de uma série sobre Jetpack Compose, ainda teremos vários outros!

Espero que tenham gostado! Todos os feedbacks são bem-vindos.

Até a próxima!

Top comments (0)