Kotlin Multiplatform Mobile

Kotlin Multiplatform Mobile

Antes de falar sobre o que é o Kotlin Multiplatform Mobile (KMM), vou começar falando o que ele NÃO é.

O KMM não é:

  • a nova bala de prata.
  • tentativa de matar o desenvolvimento nativo.
  • solução completa para aplicações multiplataforma (da UI até sua lógica de negócio).
  • não promete ser uma solução “Build once deploy everywhere”.
  • não promete simplificar ou recriar sua camada de UI.
  • framework para gerar aplicativos híbridos.

O que é?

Antes de entrarmos no Kotlin Multiplatform Mobile (KMM), é importante entendermos o que é o Kotlin Multiplatform. Trata-se de uma feature ainda experimental do Kotlin, criada pela JetBrains, que permite compartilhar código comum entre múltiplas plataformas (JavaScript, iOS, Android, desktop, etc).

De forma geral, o diagrama abaixo mostra como funciona a arquitetura do Kotlin Multiplatform.

https://kotlinlang.org/assets/images/reference/mpp/kotlin-multiplatform.png

Na camada mais interna (Common Kotlin) temos todo o código Kotlin que funciona em todas as plataformas. Contém todo o código comum, incluindo HTTP, serialização e gerenciamento de coroutines.

Na camada intermediária (Kotlin/JVM, Kotlin/JS e Kotlin/Native) temos todos os códigos Kotlin específicos necessários para cada plataforma, para garantir a interoperabilidade entre estas e o Kotlin.

Na camada mais externa (JVM Code, Native Code e Js Code) temos todo código nativo específico de cada plataforma.

A partir desse contexto, surgiu o KMM sendo uma especialização do Kotlin Multiplatform focada na plataforma mobile.

A premissa é que você pode escrever sua lógica de negócio apenas uma vez em Kotlin e usar esse código tanto no Android quanto no iOS. Porém, ainda temos a necessidade de escrever códigos de UI específicos de acordo com cada plataforma.

https://kotlinlang.org/lp/mobile/static/sdk-811ad35a3742e58b40278b7a984fc289.svg

Na imagem acima podemos entender como o KMM é estruturado. Temos nosso código compartilhado (core e lógica de negócio) e o código específico de cada plataforma sendo usados por código nativo Android e/ou iOS (geralmente views).

Padrão expect/actual

Caso seja necessário implementar algum código específico em cada plataforma (por exemplo, gerar um UUID ou acessar bluetooth) você tem a possibilidade de usar as declarações expect e actual.

Esse mecanismo é parecido com uma interface, onde o módulo compartilhado define uma declaração com a palavra chave expect e os módulos de cada plataforma proveem a declaração com a palavra chave actual escritos em Kotlin (e posteriormente compilados para Swift no caso do iOS).

https://kotlinlang.org/assets/images/reference/mpp/expect-actual.png

Concorrentes? Ou não…

Flutter: solução ponta a ponta que usa Dart como linguagem. Com o mesmo código você consegue rapidamente gerar apps Android e iOS usando a mesma camada de UI. O código Dart é compilado em bibliotecas nativas (ARM e x86) que são incorporadas num projeto executor e a partir dele, podemos gerar nossos compilados como aab/apk (Android) ou ipa (iOS).

React Native: assim como o Flutter, também oferece uma solução ponta a ponta, mas usa React (JavaScript). Antigamente, a comunicação do Javascript com o nativo era feita a partir de uma bridge bidirecional, mas com a mudança de arquitetura essa comunicação agora é feita com JSI (JavaScript Interface), fazendo com que as funções sejam chamadas diretamente através do código JavaScript do React Native.

Xamarin Native: alternativa proposta pela Microsoft que mais se aproxima do KMM. A idéia também é que você tenha seu código de UI de cada plataforma e escreva a lógica de negócios compartilhada em C#, utilizando o Visual Studio. No caso do Android, os aplicativos são compilados de C# para IL (Linguagem Intermediária) e em seguida são compilados para um assembly nativo quando o app é iniciado. No iOS, o aplicativos são compilados diretamente de C# para assembly ARM nativo. Já o Xamarin Forms se propõe a ser uma solução ponta a ponta como Flutter e React Native usando C#.

Hands-on

  1. Antes de começarmos a codar nosso aplicativo de exemplo, temos que preparar nosso ambiente de desenvolvimento.

  2. Se você for usar apenas o código compartilhado e/ou código específico para Android, poderá usar qualquer computador com sistema operacional suportado pelo Android Studio. Caso você queira usar código específico para iOS e/ou executar seu exemplo num simulador ou dispositivo físico, você vai precisar de um MacBook com macOS.

  3. Instale o Android Studio 4.1 (RC1 ou superior). Você pode usar a versão 4.0, mas o plugin do KMM para essa versão é um pouco mais limitado.
  4. Se você for escrever código específico para iOS e rodar o app iOS, instale o Xcode 11.3 ou superior.
  5. Atualize seu plugin do Kotlin para a versão 1.4.0 ou superior: no Android Studio selecione Tools | Kotlin | Configure Kotlin Plugin Updates e atualize para a última versão no canal de atualizações estáveis.
  6. Instale o plugin do Kotlin Multiplatform Mobile: No Android Studio, selecione Preferences | Plugins, procure pelo plugin Kotlin Multiplatform Mobile em Marketplace e o instale.
  7. Se você ainda não o fez, instale o JDK. Para ter certeza que você tem o JDK instalado, digite “java -version” no terminal.

2. Com o ambiente configurado, estamos prontos para criar nosso exemplo.

  • No Android Studio selecione File | New | New Project.
  • Na tela de seleção de template, uma nova opção vai aparecer (KMM Application) e você deve selecioná-la.
  • Na próxima seção, informe o nome do projeto, pacote, localização e clique em Finish e aguarde a criação/configuração do projeto.
  • Na próxima tela vamos configurar o nome da nossa aplicação Android, iOS e do módulo compartilhado, e vamos clicar em Finish novamente.

3. Depois de um longo inverno, nosso projeto foi criado. Vamos analisar o que aconteceu?

Figura 1

Na Figura 1 podemos ver três componentes principais:

  • o módulo shared: que contém todo o código compartilhado entre Android e iOS, escrito em Kotlin.
  • o módulo androidApp: que contém nosso aplicativo Android.
  • o módulo iosApp: é um projeto do Xcode que contém o app iOS.

Figura 2

Explorando mais o módulo shared (Figura 2), nós vemos que ele contém todo o código comum que funciona em ambas as plataformas. Além disso, temos os pacotes androidMain que contém código específico para Android, incluindo as implementações do actual. Já no pacote iosMain, temos todo código específico para iOS, incluindo também as implementações do actual (escritas em Kotlin).

No nosso exemplo, no pacote commonMain dentro do módulo shared temos uma classe Gretting e uma classe Platform.

Figura 3

Figura 4

Note que dentro da classe Greeting, temos um método greeting() (Figura 3) que retorna uma string e acessa um atributo da classe Platform (Figura 4), que por sua vez, não tem implementação nenhuma (observe o uso da palavra chave expect). Isso será resolvido nos pacotes específicos de cada plataforma, como veremos a seguir.

Figura 5

Figura 6

Perceba como cada plataforma atribui o valor de platform conforme sua maneira (em Kotlin), usando a palavra chave actual (Figura 5 e 6).

Atenção com o iOS aqui. Caso você não tenha o Xcode instalado, podem aparecer alguns erros (linhas vermelhas), mas isso não será problema para compilar o projeto.

Mas, como fica o uso disso nos projetos nativos? Veja um exemplo no Android:

Figura 7

Estamos chamando o método greet(), que por sua vez chama o método greeting do módulo compartilhado (Figura 7).

Veja o mesmo exemplo no projeto do iOS (Figura 8):

Figura 8

Se tivermos usando um MacBook com Xcode configurado, podemos rodar nosso app Android e iOS pelo Android Studio e aqui está o resultado (Figura 9).

Figura 9

Últimas palavras…

O objetivo desse artigo foi dar uma pequena introdução do KMM e mostrar suas possibilidades. Durante meus estudos, vi como a documentação está evoluindo rapidamente e como a JetBrains está se esforçando para que a solução seja adotada pelo maior número de pessoas possível. Eles dão sugestões de como migrar para o KMM, como organizar processos, impactos e problemas que você pode ter no time e até mesmo como introduzir o assunto com os desenvolvedores.

Conhecimento não pesa e não engorda…mesmo sendo uma pessoa que desenvolve apps nativos, acredito que valha a pena se informar sobre as soluções que estão surgindo no nosso ecossistema para ampliar o nosso repertório e nos tornar mais aptos para poder tomar melhores decisões.

Aqui estão os links que me inspiraram e que podem lhe ajudar a descobrir um pouco mais sobre o assunto.

Multiplatform programming

Kotlin Multiplatform Mobile

Connect to platform-specific APIs

Have you tried Kotlin Multiplatform?

Blog do Matheus Castiglioni | React Native é nativo?

Xamarin.Android — Xamarin

Download Android Studio and SDK tools

‎Xcode on the Mac App Store

JDK 14.0.2 GA Release

KMM documentation

JetBrains

Imagem de Peggy und Marco Lachmann-Anke por Pixabay