Comunidade

O Grande Reinício da Pilha Android: História do Design de Sistemas Móveis

O texto explora como o Android redesenhou sua arquitetura várias vezes ao longo do tempo para se adaptar às necessidades crescentes dos aplicativos. Inicialmente baseado em um modelo imperativo que exigia sincronização manual entre estado e interface, o sistema evoluiu para um modelo declarativo, onde a UI é uma função do estado, eliminando bugs comuns. Essa transformação foi impulsionada por frameworks como React, Flutter e Jetpack Compose, levando à abolição dos sistemas de visualização imperativos em plataformas nativas.

Compartilhar
The Great Android Stack Reset: Mobile System Design History · returnzero

Se você tem tempo suficiente escrevendo para Android, já viu a plataforma reescrever-se sob seus pés pelo menos três vezes. O primeiro aplicativo Android que você lançou não passaria em uma revisão de código hoje. O que segue é como isso aconteceu, por que a pilha continua reiniciando e o que qualquer candidato que aparece para uma entrevista sobre design de sistemas móveis deve saber.

A versão curta: a pilha Android não evoluiu, ela pulou. A cada poucos anos, a Google olhava para o que os aplicativos realmente faziam (vazando estado na rotação, bloqueando o thread principal com leituras de banco de dados, reinventando injeção de dependência em cada repositório) e lançava uma nova camada opinativa que tornava as soluções alternativas desnecessárias. Então a ecossistema gastava alguns anos migrando antes da próxima camada pousar. Estamos em algum lugar entre o quarto ou o quinto desses ciclos, dependendo de como você conta. O que segue é como cada ciclo se desenrolou e quais escolhas sobreviveram.

A força por trás de cada pulso: do imperativo ao declarativo

A pilha Android reiniciou porque o modelo de IU imperativa que a plataforma lançou era estruturalmente inapropriado em escala e a indústria (não apenas Android) gastou décadas convergindo para a alternativa.

No modelo imperativo, a IU e o estado são coisas separadas que você precisa manter sincronizadas manualmente. Cada transição de estado precisa ter uma chamada correspondente textView.setText(...), button.setEnabled(...), view.setVisibility(...), espalhados pelo arquivo. Essa fragilidade pode facilmente produzir bugs e fazer a IU desviar: um spinner de carregamento que nunca se dissipa, um contador obsoleto, um botão que dispara duas vezes. À medida que uma tela cresce, a superfície de sincronização também cresce com ela, e o objeto Deus do tipo Activity não era apenas um cheiro de código. Era uma estrutura que não podia escalar além de uma única tela sem os bugs de desvio pegando você.

O modelo declarativo substitui a superfície de sincronização por uma única regra: a IU é uma função do estado. Você descreve como a tela deve parecer para qualquer estado dado, o quadro de trabalho difere as árvores anteriores e atuais e aplica a diferença. A IU e o estado não podem se desviar porque eles são a mesma coisa. Não há setText para esquecer.

A UI declarativa não começou com React

O HTML em si é uma linguagem de IU declarativa. Você escreve <h1> e <button>, o navegador descobre como desenhar os pixels. A estrutura é declarada, não construída. O que impediu o HTML de ser um kit completo declarativo foi que a lógica manipulando-o, JavaScript bruto e depois jQuery, era imperativa. Você declarava o esqueleto, então você atingia nele imperativamente.

No final dos anos 1990, ferramentas RAD como Visual Basic e Delphi permitiam aos desenvolvedores criar interfaces em um editor WYSIWYG. Por trás das cortinas, esses editores geravam arquivos de layout declarativos, separando a definição da interface do lógica do programa.

Em 2004, a Macromedia lançou MXML para Flex (a Adobe adquiriu a Macromedia em 2005). Em 2006, a Microsoft lançou XAML para WPF. Ambos declaravam estrutura em marcação, mantinham lógica em uma linguagem de hospedagem e tinham vinculação de dados: conecte uma propriedade à fonte, a IU é atualizada quando a fonte muda. Eram os primeiros frameworks amplamente usados para formalizar a divisão entre layout declarativo e comportamento imperativo.

Em 2009, a Nokia introduziu QML para Qt - sintaxe semelhante ao JSON, mesma ideia. Mas enquanto MXML e XAML faziam o vinculamento opcional ({}, {Binding}), o QML o tornou padrão. Cada atribuição de propriedade era uma expressão de vinculação, reavaliada quando suas dependências mudassem. A IU era reativa por construção.

O React chegou em 2013. Ele uniu marcação e lógica de visualização em uma única unidade via JSX, e tornou a comparação barata com um DOM virtual. Em vez de declarar a estrutura em um arquivo e atualizá-la imperativamente em outro, você declarava a IU como uma função do estado em um lugar só, e o framework reconciliava a árvore. UI = f(state) tornou-se o slogan que ficou.

O React Native provou que o modelo se traduzia para mobile em 2015. O Flutter (alpha em 2017, 1.0 em 2018) levou a ideia mais longe com widgets puramente declarativos e imutáveis. Até 2019, a Apple lançou o SwiftUI e a Google anunciou o Jetpack Compose. No início dos anos 2020, cada proprietário de plataforma nativa abandonou seu sistema de visualização imperativo. O Android foi o último a seguir.

O resto deste artigo é a história de como o framework do Android se moveu em direção a uma pilha declarativa ultra opinada, um passo de cada vez.

A Era da Activity, ou: tudo era um God Object

No início havia Activity, e Activity era Deus. Você escrevia sua IU em XML, inflava no onCreate, ligava os listeners de clique no mesmo arquivo, fazia chamadas HTTP no mesmo arquivo, e escrevia para SQLite de uma thread background que roolou à mão em AsyncTask. A Activity possuía a tela, o estado, a rede, o banco de dados, e (por quê não) a lógica de negócios. Você não tinha uma arquitetura. Tinha um arquivo com 2.000 linhas.

O SO tornava essa postura cara. Rotacionar o dispositivo e o Android destruía sua Activity e construía uma nova. Tudo em andamento (sua chamada HTTP em progresso, seu formulário meio preenchido, a posição da rolagem) evaporava a menos que você tivesse empurrado através do onSaveInstanceState. A pilha era pequena, a serialização era manual, e esquecia um campo e o usuário recebia uma tela em branco. As documentações de 2013: "Sua atividade será destruída e recriada cada vez que o usuário rotacionar a tela." Isso era todo o contrato. Salve o que você se importa em onSaveInstanceState, ou perca-o na próxima rotação.

A comunidade respondeu com duas saídas de emergência. A primeira foi manter Fragments: diga a um Fragment não ser destruído em mudança de configuração, empurre seu estado e seu trabalho assíncrono para lá, e deixe a Activity ser uma concha burra. Funcionou. Também nos deu o prazer do setRetainInstance(true) e o famoso bug de Activity vazia onde seu Fragment sem cabeça sobrevivia à Activity que deveria se anexar. A segunda foi Loader - AsyncTaskLoader e CursorLoader, a primeira resposta da Google para "meu trabalho assíncrono morre na rotação". A ideia estava certa: o carregador possui o trabalho, a Activity é apenas um assinante, e o LoaderManager mantinha-o vivo durante a rotação. Isso é exatamente o que ViewModel formalizaria mais tarde. Mas a API era callbacks imperativos, e um ciclo de vida concorrente que poderia disparar callbacks em uma Activity morta. O CursorLoader foi construído para um caso de uso concreto (consultar um ContentProvider, entregar um Cursor). O AsyncTaskLoader era a classe base abstrata "faça qualquer coisa", e a Google deixou os casos de borda do ciclo de vida difícil para você descobrir. Mesmo assim, por alguns anos, foi a técnica recomendada.

O que sobreviveu desta era, conceitualmente, foi a realização de que o SO é hostil ao seu estado vivendo na IU. A equipe do Android passou a próxima década transformando essa percepção em primitivos pelos quais o resto de nós não poderia errar acidentalmente.

RxJava, MVP e a era "escolha uma arquitetura"

No meio da década de 2010, a comunidade desistiu de esperar que o Google desenvolvesse sua própria arquitetura e começou a criar suas próprias. O padrão dominante foi MVP (Model-View-Presenter), com RxJava como infraestrutura. Sua Activity era a View, seu Presenter era um POJO que se comunicava com a View através de uma interface, e seus assinantes do RxJava faziam o trabalho de mover os dados entre eles. Era realmente uma arquitetura. Também gerou milhares de variações não interoperáveis de MVP, cada uma apoiada por um post de blog que silenciosamente estava errado sobre ciclo de vida.

RxJava fazia a maior parte do trabalho pesado. Deu à Android sua primeira resposta mainstream para "como componho trabalhos assíncronos, sobrevivo às rotações e não bloqueio o thread principal". Também ensinou uma geração de engenheiros móveis o que um bug de backpressure parecia, o que significava onError não implementado (ele re-lançava no meio do seu aplicativo em produção) e que um CompositeDisposable limpo em onDestroy era a coisa mais próxima da segurança que você tinha. Era a ferramenta certa para uma plataforma que não tinha nada melhor.

A arquitetura em si, no entanto, continuava fragmentando. MVP, MVVM, MVI, Clean Architecture, os "tentativas Redux para Android": cada equipe criava a sua própria e a pergunta de entrevista "qual arquitetura seu aplicativo usa" tinha uma resposta diferente em cada empresa. O Google observou isso por cerca de três anos e então, em 2017, finalmente teve uma opinião.

A redefinição do idioma: Java para Kotlin

Antes que o Google tivesse uma opinião sobre arquitetura, ele tinha uma opinião sobre o idioma. Em 2017, o Google anunciou suporte oficial ao Kotlin em I/O. Em 2019, tornou-o a linguagem preferida. A mudança não foi cosmética. Java no Android estava envelhecendo mal, e o Kotlin foi projetado para corrigir exatamente as coisas que os desenvolvedores de Android reclamavam.

O Java ficou preso nas versões 6 e 7 por anos. O Android usava sua própria JVM (ART, anteriormente Dalvik) e estava atrasado em relação ao Java desktop. Lambdas, try-with-resources e streams chegaram tarde ou não chegaram. O Kotlin deu-lhes lambdas, segurança contra nulos, funções de extensão e desestruturação no primeiro dia, sem esperar que o sistema operacional se atualizasse.

NullPointerException foi a primeira causa de falha no Android por anos. O Kotlin tornou a nulidade uma preocupação do sistema de tipos em vez de uma surpresa em tempo de execução. String vs String? pegava bugs durante o tempo de compilação. O compilador não permitia que você desreferenciasse algo que poderia ser nulo. Isso sozinho justificou a migração para muitas equipes.

A burocracia era real. Java no Android era verboso: findViewById casts, classes anônimas internas para cada ouvinte de clique, getters e setters manuais, juggling com chaves do Bundle. As propriedades, funções de tipo, classes de dados e cortes inteligentes do Kotlin reduziram o código típico da Activity em 30 a 50 por cento. Um ouvinte de clique foi de uma classe anônima de cinco linhas para um lambda trailing.

E as coroutines resolveram o caos de threads. O RxJava funcionava, mas era pesado e difícil de ensinar. As coroutines do Kotlin (estáveis em 2018) deram concorrência estruturada que parecia código síncrono, com cancelamento e escopo de primeira classe. Isso mapeou perfeitamente no problema de ciclo de vida que o Android vinha lutando desde a era Activity: um escopo de coroutine atrelado a um ViewModel ou um lifecycleScope atrelado a uma Activity significava que o cancelamento que você costumava conectar à mão em onDestroy agora era automático.

A versão curta: Java no Android estava envelhecendo mal, Kotlin foi construído para corrigir exatamente os pontos de dor que os desenvolvedores de Android viviam e o Google jogou seu peso a favor. As documentações, amostras e ferramentas todas se moveram. Os desenvolvedores seguiram as ferramentas. Quando os Components de Arquitetura chegaram, a linguagem em que eram escritos já havia vencido.

Componentes de Arquitetura: Google envia uma opinião

No ano de 2017, a Google lançou o que chamou de Componentes de Arquitetura (Google I/O '17 talk): ViewModel, LiveData, Room e uma biblioteca de ciclo de vida que finalmente tornou o ciclo de vida algo de primeira classe em vez de um nome de método que você implementava. A proposta era simples: pare de deixar o sistema operacional destruir seu estado. Coloque seu estado em um ViewModel, que sobrevive a mudanças de configuração por design. Observe-o da Activity ou Fragment com LiveData, que é ciente do ciclo de vida e não entregará atualizações para uma tela parada. Comunique-se com o SQLite através de Room, que compila seu SQL em tipos seguros no Kotlin e retorna observáveis que você pode se inscrever. Pronto.

Foi a primeira vez que a Google enviou um conjunto, uma opinião sobre como todo o aplicativo deveria se encaixar, em vez de uma única biblioteca. O diagrama que eles colocaram na página de documentação, com a UI observando um ViewModel observando um Repository observando um banco de dados Room, tornou-se a forma canônica. Cada pergunta

Para a concepção de sistemas, o Compose tornou o modelo de renderização inspecionável. O sistema View era uma caixa preta; você o tocava, ele pintava e você esperava. Compose oferece uma árvore que você pode raciocinar sobre: a recomposição é uma função do estado, você pode estruturar seu estado de modo que apenas as partes dependentes de uma mudança sejam recompontidas, e a história de desempenho torna-se "não recomponha toda a tela em um toque" ao invés de "ore para que o ListView não apresente problemas." Isso é realmente uma vitória. Também é a razão pela qual todas as respostas modernas sobre concepção de sistemas Android agora começam com "a IU é uma função pura do estado"; essa frase não existia na plataforma antes do Compose.

O alcance mais profundo do Compose está em gerenciamento de estado. A antiga padronização era um ViewModel expondo LiveData que você observava uma vez em onCreate. O padrão do Compose é um ViewModel expondo StateFlow que você coleta com collectAsState dentro do componente que precisa disso. A IU é sem estado; o estado vive no ViewModel; o ViewModel sobrevive à rotação; a máquina de execução lida com o resto. Esta é a forma da fluxo unidirecional (UDF), e agora ela é padrão. Se você aparecer para uma entrevista móvel e descrever qualquer outra coisa, será perguntado por quê.

Hilt: finalmente chegamos a um acordo sobre injeção de dependência

Enquanto o Compose consumia a IU, o resto da pilha estava convergindo em outro eixo. A injeção de dependências no Android havia sido uma discussão de décadas. O Dagger 2 pousou em 2015 com a promessa de validação do gráfico em tempo de compilação e custo zero em tempo de execução. Ele entregou ambos. Também entregou uma curva de aprendizado que quebrou engenheiros sênior. A superfície das anotações era grande o suficiente para que a maioria das equipes tivesse um "pessoa Dagger" e todos os outros copiassem seus padrões.

Hilt, anunciado em 2020 (1.0 estável em 7 de fevereiro de 2021) (documentação), foi a resposta da Google: um gráfico Dagger pré-construído com anotações específicas para Android e um conjunto limitado de escopos. Por baixo dos panos, ainda é o Dagger. Na superfície, é uma convenção. A comunidade adotou rapidamente porque removia a "taxa de descobrir o gráfico" sem abrir mão da segurança em tempo de compilação. A página de conceitos-chave da injeção de dependência descreve a forma atual: ViewModelComponent para o encaixe entre IU e domínio, SingletonComponent para o encaixe entre domínio e dados, casos de uso com construtor simplesmente marcado como @Inject porque eles são sem estado e não precisam de módulos.

O sinal da entrevista aqui não é "você conhece Hilt" mas se você pode explicar por que os encaixes estão onde estão. A IU sabe sobre o ViewModel; o ViewModel sabe sobre casos de uso; casos de uso sabem sobre repositórios; repositórios sabem sobre Room e a rede. Nada atravessa. Isso é uma opinião arquitetônica, e Hilt é a ferramenta que a impõe em tempo de compilação.

Trabalho em segundo plano: do Service ao WorkManager

A maneira como o Android permite fazer trabalho em segundo plano foi reescrita mais vezes do que qualquer outra parte da plataforma, e é a parte que os candidatos erram mais nas entrevistas porque aprenderam uma versão e pararam de verificar.

A linhagem se estende por uma década. Service era o original primitivo de fundo, algo que roda sem interface do usuário, o que na maioria das vezes significava que rodava em primeiro plano e esvaziava a bateria. IntentService lidava com um intent por vez em uma thread de trabalho, descontinuado no API 30. JobScheduler chegou no API 21 com agrupamento gerenciado pelo sistema, a primeira resposta real para "faça este trabalho mais tarde, economicamente." Firebase JobDispatcher trouxe essa funcionalidade de volta para dispositivos pré-21 e agora está morto. AlarmManager ainda está aqui, ainda afiado, ainda fácil de esvaziar a bateria. E o WorkManager, anunciado em 2018 (versão 1.0 em 2019) (A persistência no Android é uma das poucas áreas em que a plataforma acertou a abstração cedo e não tocou mais. O Room é uma camada fina sobre o SQLite, e o SQLite está correto desde antes da existência do Android. Quando você desenha a camada de dados de um aplicativo Android em 2026, você está projetando contra a mesma restrição que a plataforma tinha em 2010: o SQLite é rápido para leituras, lento para escritas e você quer estar do lado certo dessa linha. A página de conceitos-chave de persistência explora as trade-offs em detalhes.

A camada de rede: OkHttp, Retrofit e a parte que ninguém reescreve

A pilha de rede tem sido estável há mais de uma década. O OkHttp foi lançado em 2013, tornou-se o cliente HTTP padrão do Android quase imediatamente e não foi seriamente desafiada desde então. O Retrofit (Square, 2013) fica acima como um gerador de interface tipada: você escreve uma interface Kotlin, o Retrofit produz a implementação que atinge o ponto final correto e analisa a resposta. A combinação é padrão. Quase todos os aplicativos Android que você já usou embarcam com eles.

Abaixo da superfície, os protocolos mudaram. HTTP/1.1 com keep-alive era a base. O multiplexing do HTTP/2 chegou no OkHttp 3 e fez uma diferença real em redes móveis instáveis: uma conexão, muitas solicitações em trânsito, sem bloqueio de fila da frente. QUIC e HTTP/3 ainda são nichos no lado cliente, mas o sistema operacional os suporta. A página sobre protocolos de rede explora por que isso importa para a arquitetura do sistema: um cliente móvel está falando com um servidor através de uma conexão que vai cair, limitar e mentir sobre seu tempo de ida e volta, e a escolha do protocolo muda quais desses você sente.

Daquela estabilidade veio o movimento de design de sistema que define o modelo moderno Android: tratar a rede como um transporte não confiável e colocar o trabalho de confiabilidade no cliente. Escrita otimista, uma caixa de saída, chaves idempotentes em POSTs não idempotentes, retentativas com backoff exponencial e jitter, e um canal push (FCM) que acorda o cliente quando o servidor tem novidades em vez do cliente fazer polling.

Offline-first e o padrão de caixa de saída

A frase "offline-first" esteve por aí desde os anos 2010. O que mudou na última ciclo é que parou de ser uma preocupação nichada e se tornou a expectativa padrão em entrevistas. A razão é que os aplicativos que seus usuários amam funcionam no metrô. Twitter, Gmail, Slack, Instagram: todos permitem que você role e atue offline, e todos reconciliam quando você volta online. Isso é uma decisão de arquitetura, não um recurso da interface do usuário, e é difícil.

O padrão que emergiu é a caixa de saída: toda escrita que o usuário faz vai para uma tabela local Room (a caixa de saída) na mesma transação com a atualização otimista do estado em cache. Um Worker em segundo plano esvazia a caixa de saída, atingindo o servidor com cada linha. Se o servidor não está acessível, a linha permanece. Se o servidor confirma, a linha é deletada. A caixa de saída sobrevive à morte do processo porque está no Room e sobrevive ao modo avião porque é apenas uma tabela. A intenção do usuário é durável em ambos.

A página sobre offline-first explora o padrão completo: idempotência, resolução de conflitos, o modo de falha 4xx-is-permanente. Esta é a imersão mais profunda que a maioria dos candidatos recebe e a maioria dos candidatos faz gestos vaga.

Carregamento de imagens: a única biblioteca que todos concordam

O carregamento de imagens no Android tem um consenso silencioso que o resto da pilha poderia aprender com. Picasso (Square, 2013) foi o vencedor inicial. Glide (2014) assumiu a liderança e permaneceu dominante por anos: rápido, funcionalmente completo, com uma API ciente do ciclo de vida que lidava com o problema "a Activity desapareceu, por que você ainda está decodificando este bitmap". Coil (2019, primeiro em Kotlin, nativo para Coroutines) é a biblioteca padrão atual para projetos baseados em Compose e é o que vem com o modelo de aplicativo Android.

Toda biblioteca de carregamento de imagens resolve um conjunto específico de problemas, e esses problemas são os mesmos sobre os quais você será questionado em entrevistas: decodificação sem OOM (Out of Memory), cache em duas camadas, pools de conexões compartilhados, o truque da proporção antes dos bytes. Internos de carregamento de imagens aborda-os em profundidade. A biblioteca lida com tudo isso; se você sabe o que ela está fazendo por você é o que a entrevista realmente verifica.

Paginação: offset está errado, cursor está certo e aqui está por quê

A paginação é o lugar onde a opinião da plataforma e a opinião do servidor precisam concordar, e o lugar onde a maioria dos candidatos escolhe o primitivo errado. Paging 3 é a biblioteca atual; ela envia um RemoteMediator que lida com a "carregue da rede e armazene no Room, apresente uma única stream para a UI" coreografia. A estratégia importa mais do que a biblioteca.

A paginação por offset (página 1 = itens 0-19, página 2 = itens 20-39) quebra o momento em que qualquer coisa é inserida no topo. Os timestamps de cursor quebram em empates e re-ranking. O que sobrevive é um cursor definido pelo servidor opaco: o servidor dá ao cliente uma token não interpretada, o cliente a devolve na próxima solicitação e o servidor está livre para re-classificar, inserir e excluir sem quebrar o cliente.

O página de paginação caminha pelos trade-offs em detalhes. Assim como a imersão no offline-first, a questão é se você pode nomear o modo de falha do escolha óbvia e defender a alternativa, não se você pode recitar a API.

O modelo, conforme de 2026

Empilhe tudo acima e você obtém o modelo padrão atual do aplicativo Android, que é o que cada resposta moderna em entrevistas é avaliada. O modelo de aplicativo Android caminha por ele do início ao fim: Compose sobre StateFlow, casos de uso com @Inject constructor, repositórios sobre um cache em duas camadas com uma caixa de saída, Hilt nas bordas, WorkManager para trabalho durável no background, Coil, Paging 3.

Cada peça desse modelo é uma escolha e cada escolha tem uma alternativa que alguém defenderá. O ponto não é que está certo mas que é o consenso atual, o que significa que é a posição inicial da qual você precisa justificar se afastar.

O próximo salto já começou

O modelo acima é o que a plataforma convergiu, e está mudando. Compose Multiplatform é real. Kotlin Multiplatform (KMP) está puxando as camadas de domínio e dados do Android JVM para iOS, desktop e servidor; o padrão "compartilhe tudo, mas não a UI" está começando a parecer o padrão por novos aplicativos em branco. A abstração ViewModel pode não sobreviver ao próximo ciclo como algo específico do Android. Room já roda no KMP. Hilt está sendo desafiado por soluções de DI multiplataforma como kotlin-inject e Metro que compilam para gráficos multiplataforma.

Esta não é uma aposta especulativa. A Netflix lançou o KMP em seus aplicativos Android e iOS em produção. A McDonald's migrou seu aplicativo inteiro para KMP após um teste bem-sucedido de pagamentos, relatando menos crashes e melhor desempenho em ambas as plataformas. A Forbes compartilha mais de 80% da lógica móvel entre iOS e Android. E a própria equipe do Google Workspace validou o KMP no experimento do Google Docs e chamou-o de sucesso.

O que sobreviverá ao próximo salto, da mesma forma que as fronteiras das camadas sobreviveram à mudança de Activities para Compose, é a opinião arquitetônica. As camadas, os pontos de interconexão, o outbox, a troca de paginação cursor, o contrato offline-first, o movimento de push como gatilho e não como verdade são opiniões móveis, não Android, e transferirão limpidamente para qualquer próxima camada do sistema.

Linhas do tempo em resumo

AnoÉpocaO que mudou
2008A Era das ActivitiesUma Activity por tela, objeto Deus por arquivo, o sistema operacional recolhia seu estado em cada rotação.
2011Cargas e FragmentsAsyncTaskLoader tentou sobreviver às mudanças de configuração. Ele não conseguiu na maioria das vezes.
2017Kotlin como primeira classeA Google anuncia o suporte ao Kotlin em I/O. A mudança para a linguagem começa.
2017Camadas de ArquiteturaViewModel, LiveData, Room. A Google finalmente enviou uma opinião.
2018Coroutines estáveisA concorrência estruturada chega. O substituto do RxJava chega.
2019Kotlin preferidoA Google faz o Kotlin a linguagem preferida. Os documentos mudam.
2019Jetpack Compose anunciadoA camada de interface do usuário recebe uma nova chance. O público XML se põe em pânico, então aprende silenciosamente Kotlin.
2021Compose 1.0 + ciclo betaO modelo cristaliza: Compose + ViewModel + Flow + Room + Hilt.
2024A linha de base mudaCompose Multiplatform, KMP, o modelo começa a se espalhar além do telefone.

Onde ir mais fundo

O catálogo caminha por cada camada do modelo atual em profundidade. A ordem correta para um loop de preparação de design de sistema móvel:

A pilha continuou se reiniciando porque a plataforma continuava revelando uma restrição que havia imporindo silenciosamente o tempo todo: o estado não sobrevive ao sistema operacional, e a rede é hostil. Cada nova camada é um jeito de tornar essa restrição mais difícil de esquecer. O modelo que temos agora é aquele onde derramar estado em rotação, bloquear a interface do usuário ou perder uma escrita no modo avião tudo exige esforço deliberado. O próximo será o que escrever um aplicativo uniplataforma também.

Fonte original

Conteúdo traduzido e adaptado pela redação do Notícias Mobile. Confira também a matéria na fonte original.

Leia a matéria completa