Olá pessoal. Antes de partir para o fim de semana, nos apressamos em compartilhar com você outra tradução preparada especialmente para os alunos do
Desenvolvedor Android. Curso avançado .
”
Tentando uma nova estrutura de interface do usuário para aplicativos Android
Nos últimos anos, participando de muitos projetos móveis, tive que usar várias tecnologias, como Android, ReactNative e Flutter. Mudar de ReactNative de volta para o Android clássico me fez sentir confuso. O retorno ao Kotlin correu bem, mas eu realmente senti falta da estrutura do React UI. Os pequenos componentes reutilizáveis que compõem a interface do usuário são ótimos e fornecem mais flexibilidade e velocidade de desenvolvimento.
De volta ao Android clássico, eu precisava me preocupar em manter a hierarquia do View o mais uniforme possível. Por isso, é difícil dedicar-se verdadeiramente à abordagem dos componentes. Isso torna a copiar e colar mais atraente, o que leva a um código mais complexo e com menos suporte. Por fim, evitamos experimentar uma interface do usuário que possa melhorar o UX.
O Android revela o Jetpack Compose. Ilustração: Emanuel BagillaJetpack Compor para o resgate
Portanto, depois de assistir
às novidades do Android na conferência Google I / O 2019, comecei imediatamente a lidar com o Compose e tentei aprender mais sobre ele. Compose é um kit de ferramentas de interface de usuário reativo totalmente desenvolvido pela Kotlin. A composição é muito semelhante às estruturas existentes da interface do usuário, como React, Litho ou Flutter.
A estrutura atual da estrutura da interface do usuário do Android existe desde 2008 e, com o tempo, tornou-se mais complexa, sendo bastante difícil de manter. O Jetpack Compose visa começar desde o início, levando em consideração a filosofia dos componentes modernos. A estrutura foi escrita com os seguintes objetivos principais em mente:
- Inconsistência com as versões da plataforma: isso permite que você corrija rapidamente os erros, pois o Compose não depende de novas versões do Android.
- Pilha de tecnologia menor: a estrutura não obriga a usar o View ou o Fragment ao criar uma interface do usuário. Todos os elementos são componentes e podem ser livremente compostos juntos.
- Gerenciamento transparente de estados e manipulação de eventos: Uma das coisas mais importantes e complexas que você precisa resolver em grandes aplicativos é o processamento do fluxo e do estado dos dados na interface do usuário. A composição esclarece quem é o responsável pelo estado e como os eventos devem ser tratados, semelhante à maneira como o React lida com ele.
- Escrevendo menos código: escrever uma interface de usuário no Android geralmente requer muito código, especialmente ao criar layouts mais complexos, por exemplo, usando o RecyclerView. O Compose visa simplificar bastante a maneira de criar uma interface de usuário.
Isso facilita a criação de componentes isolados e reutilizáveis, facilitando a criação de uma nova tela com os elementos existentes. Ajudando você, como desenvolvedor, a se concentrar na criação de uma interface de usuário conveniente, em vez de tentar controlar a hierarquia de exibição e a exibição e fragmento doméstico.
Uma aplicação simples com Compose: Hello World
Vamos dar uma olhada no código de um aplicativo simples Hello World com o 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 }) } } }
No método
onCreate
definimos o conteúdo de nosso aplicativo chamando
setContent
. Este é um método que inicializa uma árvore de widget composta e a
FrameLayout
em um
FrameLayout
.
Para fazê-lo funcionar, precisamos
CraneWrapper
nosso aplicativo no
CraneWrapper
e no
MaterialTheme
.
CraneWrapper
é responsável pela configuração de provedores para
Context
,
FocusManager
e
TextInputService
.
MaterialTheme
necessário para fornecer as cores, estilos e fontes dos seus widgets. Com isso em mente, podemos adicionar o componente
Text
, que exibirá nosso texto na tela em um determinado estilo.
Introdução do estado
Gerenciar o fluxo de dados e os estados pode ser uma tarefa assustadora. Para ilustrar como é fácil com o Compose, vamos criar um aplicativo de contador simples.
Para trabalhar com estados, o Jetpack Compose usa as idéias de outras estruturas modernas de interface do usuário, como Flutter e React. Existe um fluxo de dados unidirecional e reativo que faz com que seu widget seja atualizado ou "reconstruído".
@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}") } }
No exemplo acima, adicionamos os botões "Adicionar" e "Subtrair", juntamente com um rótulo que exibe o número atual de cliques. Como você pode ver no exemplo abaixo, atualizando o estado "quantia", os widgets são reorganizados de maneira inteligente quando o estado muda.
Iniciar um aplicativo de demonstraçãoO estado da
amount
é inicializado com
+state { 0 }
. Tentando descobrir que tipo de bruxaria é, entrei no código fonte. Esta é a minha opinião, embora ainda não tenha certeza de que compreendo tudo.
state {...}
cria um
Effect<
State <
T <
code>>
. A classe
Effect
é uma classe difusa que contém um bloco de código executável que é executado posicionalmente no contexto de uma composição. A classe
State
contém um valor com o tipo
Model
, essencialmente tornando esse valor observável. O operador + é um operador temporário que resolve o
State
do
Effect
.
Modelos de Estado Customizados
Em vez de usar
+state {}
para criar um modelo de valor único, também podemos criar um modelo personalizado usando a anotação @Model. Podemos melhorar nosso aplicativo de contador dividindo-o em widgets menores e passando o modelo para outros widgets atualizados e exibindo o estado desse modelo.
@Model class CounterModel { var counter: Int = 0 var header = "Counter demo" fun add() { counter++ } fun subtract() { counter-- } }
Usando a anotação
@Model
, o plug-in Compose Compiler torna todas as variáveis em seu modelo observáveis, para que possam ser usadas para reorganizar widgets. Vamos atualizar nosso widget para usar o
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}") }
O único widget no qual o aplicativo giratório consiste agora é dividido em vários widgets composíveis menores.
CounterModel
é passado para vários widgets, para exibir o estado do modelo ou para alterar o estado do modelo usando as funções
add()
ou
subtract()
.
Não há mais vista
É importante entender que os widgets do Jetpack Compose não usam view ou fragment sob o capô, essas são apenas as funções que desenham na tela. O plug-in Compose Compiler processa todas as funções com a anotação
@Composable
e atualiza automaticamente a hierarquia da interface do usuário.
Por exemplo, um widget
Divider
consiste em um widget
Padding
que contém um widget
DrawFillRect
. Observando o código fonte do
DrawFillRect
, fica claro que ele desenha linhas diretamente na tela. Todos os outros widgets são implementados da mesma maneira.
@Composable private fun DrawFillRect(brush: Brush) { Draw { canvas, parentSize -> val paint = Paint() brush.applyBrush(paint) canvas.drawRect(parentSize.toRect(), paint) } }
O código-fonte do DrawFillRect usado dentro do widget Divisor.
Se olharmos para o Inspetor de layout iniciando um dos aplicativos de exemplo do Google, veremos claramente que, ao iniciar o aplicativo Android com o Compose, não há
View
ou
ViewGroups
. Vemos um
FrameLayout
contendo o
CraneWrapper
que criamos no código; a partir daí, a hierarquia da composição da interface do usuário é exibida na tela.
O Inspetor de layout inspeciona o Jetpack Compose.A ausência de visualizações também significa que o Jetpack Compose não pode usar as visualizações disponíveis no momento, como
android.widget.Button
, e deve criar todos os widgets do zero. Se você observar, por exemplo, Flutter, que usa a mesma abordagem, pode ver que isso é um trabalho árduo. Esse é um dos motivos pelos quais o Jetpack Compose precisará de tempo antes de estar pronto para uso na produção.
Todos os elementos são widgets.
Assim como Flutter, em Compose todos os elementos são widgets. Widgets mais complexos foram divididos em widgets elementares com responsabilidades claras. Portanto, mesmo preenchimento, espaçadores e assim por diante são widgets. Por exemplo, se você deseja adicionar recuo ao redor de um botão, basta envolvê-lo no widget de preenchimento:
Padding(padding = 16.dp) { Button(text = "Say hello", onClick = { ... }) }
Conectando código à interface do usuário
Combinar código Kotlin com widgets da interface do usuário é muito fácil. Por exemplo, se você deseja mostrar uma interface do usuário que repita ou depende de algumas condições. Portanto, você pode exibir facilmente uma lista de nomes, como mostrado abaixo.
Column { listOf("John", "Julia", "Alice", "Mark").forEach { Text(text = it) } }
Esse é um recurso realmente poderoso, mas você deve ter cuidado para não programar muita lógica no nível da interface do usuário.
Compatível com seus aplicativos Android
A composição foi projetada para que você possa adicioná-lo a um aplicativo existente e transferir gradualmente algumas partes da sua interface do usuário para uma nova estrutura. Os exemplos acima adicionam a interface do usuário do Jetpack Compose a uma atividade. Você também pode incorporar widgets de composição em um layout XML existente usando a anotação
GenerateView
:
@Composable @GenerateView fun Greeting(name: String) { }
Conclusão
Estou encantado com o Compose, porque reduz o sofrimento crescente que experimento ao desenvolver para o Android. Ajuda a ser mais flexível, o foco na criação de uma interface de usuário conveniente e a responsabilidade clara também ajuda a evitar erros.
A composição tem um longo caminho a percorrer, na minha opinião, pode ser usada na produção antes de um ou dois anos. No entanto, acho que é um bom momento para dar uma olhada no Jetpack Compose. Os criadores estão procurando ativamente feedback; nesse estágio, você ainda pode fazer alterações. Todas as revisões ajudarão a melhorar essa nova estrutura.
Leia meu artigo
Try Jetpack Compose today para saber como conectar o Compose pré-alfa. Além disso, acho que será muito interessante assistir a um
vídeo sobre modelos de interface declarativa com o Google I / O.
Estou ansioso para saber quando posso usar o Compose em aplicativos Android reais!
Isso é tudo. Aguardamos seus comentários e tenha um ótimo final de semana!