Depois de assistir a uma palestra sobre o Android Jetpack Compose no Google IO 2019, eu quis experimentar imediatamente. Além disso, a abordagem implementada lembrou muito a Flutter, da qual eu estava interessado anteriormente .

A própria biblioteca de composição está no estágio pré-alfa; portanto, não existem muitas documentações e artigos sobre ela. Em seguida, contarei com vários recursos que consegui encontrar, além da biblioteca de código aberto .
Esses recursos são:
O que é o Android Jetpack Compose?
Anteriormente, toda a interface do usuário do Android era baseada na classe View. Este tem sido o caso desde os primeiros dias do Android. E nesse sentido, muitas falhas herdadas e arquitetônicas se acumularam, o que poderia ser aprimorado. Mas fazer isso é bastante difícil sem quebrar todo o código escrito em sua base.
Nos últimos anos, muitos novos conceitos apareceram no mundo dos aplicativos clientes (incluindo as tendências do Frontend); portanto, a equipe do Google seguiu um caminho radical e reescreveu todo o nível da interface do usuário no Android. Assim, apareceu a biblioteca Android Jetpack Compose, que inclui truques conceituais de React, Litho, Vue, Flutter e muitos outros.
Vamos examinar alguns dos recursos da interface do usuário existente e compará-lo com o Redigir.
1. Independência das versões do Android
A interface do usuário existente está intimamente relacionada à plataforma. Quando os primeiros componentes do Design de materiais apareceram, eles funcionavam apenas com o Android 5 (API21) e superior. Para trabalhar em versões mais antigas do sistema, você deve usar a Biblioteca de Suporte.
O Compose faz parte do Jetpack, que o torna independente das versões do sistema e é possível usá-lo mesmo em versões mais antigas do Android (pelo menos com a API21).
2. Toda a API do Kotlin
Anteriormente, era necessário lidar com arquivos diferentes para criar uma interface do usuário. Descrevemos a marcação em xml e, em seguida, usamos o código Java / Kotlin para fazê-lo funcionar. Depois voltamos a outros arquivos xml para definir temas, animação, navegação, ... E até tentamos escrever código em xml (Data Binding).
O uso do Kotlin permite que você escreva UIs de estilo declarativo diretamente no código, em vez de xml.
3. Composable = Composite: usando composição em vez de herança
Criar elementos de interface do usuário personalizados pode ser bastante complicado. Precisamos herdar do View ou de seus descendentes e cuidar de muitas propriedades importantes antes de iniciar corretamente. Por exemplo, a classe TextView contém cerca de 30 mil linhas de código Java. Isso se deve ao fato de que ela contém muita lógica desnecessária que é herdada por elementos descendentes.
A composição surgiu por outro lado, substituindo herança por composição.
Padding
é o mais adequado para ilustrar o que é:
Na interface do usuário existente, para renderizar o TextView
recuado em 30dp
:
precisamos escrever o seguinte código:
<TextView android:id="@+id/simpleTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/cyan" android:padding="30dp" <------------------------ NOTE THIS android:text="Drag or tap on the seek bar" />
Isso significa que em algum lugar dentro do TextView.java ou em suas superclasses existe uma lógica que sabe como contar e desenhar recuos.
Vamos ver como você pode fazer o mesmo no Compose:
Alterações
TextView
tornou apenas Text()
. A propriedade android:padding
se transformou em um Padding
que envolve o Text
.
Os benefícios
Assim, o Text
é responsável apenas por renderizar o próprio texto. Ele não sabe contar travessões. Padding
, por outro lado, é responsável apenas pelo preenchimento e nada mais. Pode ser usado em torno de qualquer outro elemento.
4. Fluxo de dados unidirecional
O fluxo de dados unidirecional é um conceito importante se falarmos, por exemplo, sobre o controle do estado de um CheckBox
em um sistema de interface do usuário existente. Quando o usuário toca na CheckBox
, seu estado fica checked = true
: a classe atualiza o estado View e chama um retorno de chamada do código que monitora a alteração do estado.
Em seguida, no próprio código, por exemplo, no ViewModel
, você precisa atualizar a variável de state
correspondente. Agora você tem duas cópias do estado pressionado, o que pode criar problemas. Por exemplo, alterar o valor da variável de state
dentro do ViewModel
fará com que o CheckBox
atualizado, o que pode terminar em um loop sem fim. Para evitar isso, teremos que criar algum tipo de muleta.
Usar o Compose ajudará a resolver esses problemas, pois ele se baseia no princípio da unidirecionalidade. A mudança de estado será processada dentro da estrutura: simplesmente fornecemos o modelo de dados para dentro. Além disso, o componente no Compose agora não altera seu estado por conta própria. Em vez disso, ele apenas chama de retorno de chamada e agora é tarefa do aplicativo alterar a interface do usuário.
5. Melhorando a depuração
Como toda a interface do usuário agora está escrita no Kotlin, você pode depurar a interface do usuário. Eu não tentei isso sozinho, mas no podcast eles disseram que o depurador e os pontos de interrupção funcionam no Compose.
Palavras suficientes, mostre o código
Eu sei, quero ver rapidamente como é a interface do usuário no código (spoiler: muito semelhante ao Flutter se você tentar escrever nele).
Começaremos criando algumas View
simples e comparando a aparência delas na interface do usuário existente e em Compor.
1. FrameLayout
vs Wrap + Padding + Background
Reutilizamos nosso exemplo acima e tentamos fazer esse TextView
recuado a 30dp
com um fundo turquesa:
UI existente:
<TextView android:id="@+id/simpleTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/cyan" <-------------- NOTE THIS android:padding="30dp" <------------------------ AND THIS android:text="Drag or tap on the seek bar" />
Agora observe o código que faz o mesmo em Redigir:
@Composable fun MyText() { Wrap { Padding(30.dp) { DrawRectangle(color = Color.Cyan) Text("Drag or tap on the seek bar") } } }
Aqui estão algumas coisas novas. Como o Text
sabe apenas sobre a renderização, ele não se importa com preenchimento e plano de fundo. Portanto, para adicioná-los, precisamos usar três funções separadas:
DrawRectangle
plano de fundoPadding
Wrap
automática é uma função que sobrepõe parâmetros como FrameLayout
.
Fácil. Mas é um pouco diferente do sistema de interface do usuário existente com o qual estamos acostumados.
2. LinearLayout
vertical vs Column
Agora vamos tentar fazer algo equivalente ao nosso bom e velho LinearLayout
.
Para colocar dois elementos um abaixo do outro, como na figura abaixo, podemos usar a Column
:
O código ficará assim:
@Composable fun FormDemo() { Column(crossAxisAlignment = CrossAxisAlignment.Start) { Text("Click the button below: ") Button(text = "Next") } }
Aninhado no elemento Column
será localizado verticalmente um abaixo do outro.
2a Indentação
Você provavelmente notou que o texto e o botão estão muito próximos da borda. Portanto, adicione Padding
.
@Composable fun FormDemo() { Padding(10.dp) {
Parece melhor:
2b. Intervalos
Também podemos adicionar alguma indentação entre Text
e Button
:
@Composable fun FormDemo() { Padding(10.dp) { Column(crossAxisAlignment = CrossAxisAlignment.Start) { Text("Click the button below: ") HeightSpacer(10.dp)
Como é nossa tela agora:
2c. Horizontal LinearLayout
vs Row
Coloque o segundo botão ao lado do primeiro:
Código para isso:
@Composable fun FormDemo() { Padding(10.dp) { Column(crossAxisAlignment = CrossAxisAlignment.Start) { Text("Click the button below: ") HeightSpacer(10.dp) Row {
Dentro da Row
dois botões estarão na horizontal. WidthSpacer
adiciona distância entre eles.
2d. Gravity
vs Alignment
Alinhe nossos elementos no centro, como a gravity
faz na interface atual. Para mostrar diff, vou comentar as linhas antigas e substituí-las por novas:
@Composable fun FormDemo() { Padding(10.dp) {
Teremos sucesso:
Com crossAxisAlignment = CrossAxisAlignment.Center
os elementos aninhados serão centralizados horizontalmente. Também devemos definir o parâmetro Row
como mainAxisSize = FlexSize.Min
, semelhante em comportamento a layout_width = wrap_content
, para que não se estenda pela tela devido ao padrão mainAxisSize = FlexSize.Max
, que se comporta como layout_width = match_parent
.
2d. Observação
Pelo que vimos nos exemplos acima, você pode ver que todos os elementos são construídos compostos de funções separadas: o padding
é uma função separada, o spacer
é uma função separada, em vez de ser propriedades dentro de Text
, Button
ou Column
.
Elementos mais complexos, como RecyclerView
ou ConstraintLayout
estão em desenvolvimento: portanto, não consegui encontrar um exemplo com eles nas fontes de demonstração.
3. Estilos e Temas
Você provavelmente notou que os botões acima são roxos por padrão. Isso ocorre porque eles usam estilos padrão. Vamos ver como os estilos funcionam no Compose.
Nos exemplos acima, FormDemo
marcado com anotação @Composable
. Agora vou mostrar como esse elemento é usado na Activity
:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper{ MaterialTheme { FormDemo() } } } }
Em vez da função setContentView()
, usamos setContent()
, uma função de extensão da biblioteca Compose.kt
.
CraneWrapper
contém a árvore de composição e fornece acesso a Context
, Density
, FocusManager
e TextInputService
.
MaterialTheme
permite personalizar o tema para elementos.
Por exemplo, posso alterar a cor principal do tema para marrom da seguinte maneira:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper{
Agora nossa tela ficará assim:
Outras cores e fontes que podem ser alteradas: MaterialTheme.kt # 57
O Rally Activity fornece um bom exemplo de como personalizar um tópico: código fonte para RallyTheme.kt
O que ver / ler
Se você quiser mais, poderá montar o projeto de amostra de acordo com as instruções aqui .
Como os usuários do Windows escrevem, agora não há uma maneira oficial de iniciar o Compose, mas há um guia não oficial do kotlinlang Slack .
Perguntas sobre o Compose podem ser feitas aos desenvolvedores no canal #compose
kotlinlang Slack.
Deixe outros links nos comentários - os mais úteis serão adicionados aqui.
Conclusões
O desenvolvimento desta biblioteca está em pleno andamento, portanto, quaisquer interfaces mostradas aqui estão sujeitas a alterações. Ainda há muitas coisas que você pode aprender no código-fonte, como @Model
e fluxo de dados unidirecional (fluxo de dados unidirecional). Talvez este seja um tópico para artigos futuros.