Olá, Jetpack Compose
Tiago Taraczuk
Posted on March 15, 2021
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.
- O texto deverá ser da cor verde caso o saldo seja maior ou igual a zero;
- 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" />
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"
}
E no modelo declarativo:
@Composable
fun UserBalance(balance: Double) {
Text(
text = "$balance",
color = if (balance >= 0) Color.Green else Color.Red,
)
}
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!")
}
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:
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!")
}
}
Esse é o resultado:
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!")
}
}
}
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:
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.")
}
}
Nesse caso, toda vez que o numberOfClicks
for alterado, o Button
passará pelo recomposition.
Resultado:
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!
Posted on March 15, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.