Dez recursos Kotlin para impulsionar o desenvolvimento do Android
Publicados: 2022-03-11Introdução
Há algum tempo, Tomasz introduziu o desenvolvimento Kotlin no Android. Para lembrá-lo: Kotlin é uma nova linguagem de programação desenvolvida pela Jetbrains, a empresa por trás de um dos IDEs Java mais populares, o IntelliJ IDEA. Assim como Java, Kotlin é uma linguagem de propósito geral. Como ele está em conformidade com o bytecode da Java Virtual Machine (JVM), ele pode ser usado lado a lado com o Java e não vem com sobrecarga de desempenho.
Neste artigo, abordarei os 10 principais recursos úteis para impulsionar seu desenvolvimento Android.
Nota : no momento da redação deste artigo, as versões reais eram o Android Studio 2.1.1. e Kotlin 1.0.2.
Configuração Kotlin
Como o Kotlin é desenvolvido pela JetBrains, ele é bem suportado no Android Studio e no IntelliJ.
O primeiro passo é instalar o plugin Kotlin. Depois de fazer isso com sucesso, novas ações estarão disponíveis para converter seu Java para Kotlin. Duas novas opções são:
- Crie um novo projeto Android e configure o Kotlin no projeto.
- Adicione suporte a Kotlin a um projeto Android existente.
Para saber como criar um novo projeto Android, consulte o guia passo a passo oficial. Para adicionar suporte a Kotlin a um projeto recém-criado ou existente, abra a caixa de diálogo de ação de localização usando Command + Shift + A
no Mac ou Ctrl + Shift + A
no Windows/Linux e invoque a ação Configure Kotlin in Project
.
Para criar uma nova classe Kotlin, selecione:
-
File
>New
>Kotlin file/class
ou -
File
>New
>Kotlin activity
Alternativamente, você pode criar uma classe Java e convertê-la em Kotlin usando a ação mencionada acima. Lembre-se, você pode usá-lo para converter qualquer classe, interface, enumeração ou anotação, e isso pode ser usado para comparar Java facilmente com código Kotlin.
Outro elemento útil que economiza muita digitação são as extensões Kotlin. Para usá-los, você deve aplicar outro plugin no arquivo build.gradle
do seu módulo:
apply plugin: 'kotlin-android-extensions'
Advertência : se você estiver usando a ação do plug-in Kotlin para configurar seu projeto, ele colocará o seguinte código em seu arquivo build.gradle
de nível superior:
buildscript { ext.kotlin_version = '1.0.2' repositories { jcenter() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } }
Isso fará com que a extensão não funcione. Para corrigir isso, basta copiar esse código para cada um dos módulos do projeto em que você deseja usar o Kotlin.
Se você configurar tudo corretamente, poderá executar e testar seu aplicativo da mesma forma que faria em um projeto Android padrão, mas agora usando Kotlin.
Economizando tempo com Kotlin
Então, vamos começar descrevendo alguns aspectos-chave da linguagem Kotlin e fornecendo dicas sobre como você pode economizar tempo usando-a em vez de Java.
Recurso nº 1: importação de layout estático
Um dos códigos clichê mais comuns no Android é usar a função findViewById()
para obter referências às suas visualizações em Atividades ou Fragmentos.
Existem soluções, como a biblioteca Butterknife, que economizam um pouco de digitação, mas o Kotlin dá mais um passo, permitindo que você importe todas as referências às visualizações do layout com uma importação.
Por exemplo, considere o seguinte layout XML de atividade:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:andro xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="co.ikust.kotlintest.MainActivity"> <TextView android: android:layout_width="wrap_content" android:layout_height="wrap_content"/> </RelativeLayout>
E o código de atividade que o acompanha:
package co.ikust.kotlintest import android.support.v7.app.AppCompatActivity import android.os.Bundle import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) helloWorldTextView.text = "Hello World!" } }
Para obter as referências de todas as visualizações no layout com um ID definido, use a extensão Android Kotlin Anko. Lembre-se de digitar esta instrução de importação:
import kotlinx.android.synthetic.main.activity_main.*
Observe que você não precisa escrever ponto e vírgula no final das linhas em Kotlin porque eles são opcionais.
O TextView
do layout é importado como uma instância TextView
com o nome igual ao ID da visualização. Não se confunda com a sintaxe, que é usada para definir o rótulo:
helloWorldTextView.text = "Hello World!"
Cobriremos isso em breve.
Advertências :
- Certifique-se de importar o layout correto, caso contrário, as referências de exibição importadas terão um valor
null
. - Ao usar fragmentos, certifique-se de que as referências de View importadas sejam usadas após a chamada da função
onCreateView()
. Importe o layout na funçãoonCreateView()
e use as referências View para configurar a interface do usuário emonViewCreated()
. As referências não serão atribuídas antes que o métodoonCreateView()
termine.
Recurso #2: Escrevendo classes POJO com Kotlin
Algo que vai economizar mais tempo com Kotlin é escrever as classes POJO (Plain Old Java Object) usadas para armazenar dados. Por exemplo, no corpo da solicitação e resposta de uma API RESTful. Em aplicativos que dependem da API RESTful, haverá muitas classes como essa.
Em Kotlin, muito é feito por você, e a sintaxe é concisa. Por exemplo, considere a seguinte classe em Java:
public class User { private String firstName; private String lastName; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } }
Ao trabalhar com Kotlin, você não precisa escrever a palavra-chave pública novamente. Por padrão, tudo é de escopo público. Por exemplo, se você quiser declarar uma classe, basta escrever:
class MyClass { }
O equivalente do código Java acima em Kotlin:
class User { var firstName: String? = null var lastName: String? = null }
Bem, isso economiza muita digitação, não é? Vamos percorrer o código Kotlin.
Ao definir variáveis em Kotlin, existem duas opções:
- Variáveis mutáveis, definidas pela palavra-chave
var
. - Variáveis imutáveis, definidas pela palavra-chave
val
.
A próxima coisa a notar é que a sintaxe difere um pouco do Java; primeiro, você declara o nome da variável e depois segue com o tipo. Além disso, por padrão, as propriedades são tipos não nulos, o que significa que não podem aceitar valor null
. Para definir uma variável para aceitar um valor null
, um ponto de interrogação deve ser adicionado após o tipo. Falaremos sobre isso e sobre segurança nula em Kotlin mais tarde.
Outra coisa importante a ser observada é que o Kotlin não tem a capacidade de declarar campos para a classe; somente propriedades podem ser definidas. Portanto, neste caso, firstName
e lastName
são propriedades que receberam métodos getter/setter padrão. Como mencionado, no Kotlin, ambos são públicos por padrão.
Os acessadores personalizados podem ser escritos, por exemplo:
class User { var firstName: String? = null var lastName: String? = null val fullName: String? get() firstName + " " + lastName }
Do lado de fora, quando se trata de sintaxe, as propriedades se comportam como campos públicos em Java:
val userName = user.firstName user.firstName = "John"
Observe que a nova propriedade fullName
é somente leitura (definida pela palavra-chave val
) e possui um getter customizado; ele simplesmente acrescenta nome e sobrenome.
Todas as propriedades em Kotlin devem ser atribuídas quando declaradas ou estão em um construtor. Há alguns casos em que isso não é conveniente; por exemplo, para propriedades que serão inicializadas por meio de injeção de dependência. Nesse caso, um modificador lateinit
pode ser usado. Aqui está um exemplo:
class MyClass { lateinit var firstName : String; fun inject() { firstName = "John"; } }
Mais detalhes sobre as propriedades podem ser encontrados na documentação oficial.
Recurso #3: Herança de Classe e Construtores
Kotlin também tem uma sintaxe mais concisa quando se trata de construtores.
Construtores
As classes Kotlin têm um construtor primário e um ou mais construtores secundários. Um exemplo de definição de um construtor primário:
class User constructor(firstName: String, lastName: String) { }
O construtor primário vai após o nome da classe na definição de classe. Se o construtor primário não tiver anotações ou modificadores de visibilidade, a palavra-chave do construtor poderá ser omitida:
class Person(firstName: String) { }
Observe que um construtor primário não pode ter nenhum código; qualquer inicialização deve ser feita no bloco de código init
:
class Person(firstName: String) { init { //perform primary constructor initialization here } }
Além disso, um construtor primário pode ser usado para definir e inicializar propriedades:
class User(var firstName: String, var lastName: String) { // ... }
Assim como as regulares, as propriedades definidas a partir de um construtor primário podem ser imutáveis ( val
) ou mutáveis ( var
).
As classes também podem ter construtores secundários; a sintaxe para definir um é a seguinte:
class User(var firstName: String, var lastName) { constructor(name: String, parent: Person) : this(name) { parent.children.add(this) } }
Observe que todo construtor secundário deve delegar a um construtor primário. Isso é semelhante ao Java, que usa this
palavra-chave:
class User(val firstName: String, val lastName: String) { constructor(firstName: String) : this(firstName, "") { //... } }
Ao instanciar classes, observe que Kotlin não possui new
palavras-chave, assim como Java. Para instanciar a classe User
mencionada acima, use:
val user = User("John", "Doe)
Apresentando a herança
Em Kotlin, todas as classes se estendem de Any
, que é semelhante a Object
em Java. Por padrão, as classes são fechadas, como as classes finais em Java. Portanto, para estender uma classe, ela deve ser declarada como open
ou abstract
:
open class User(val firstName, val lastName) class Administrator(val firstName, val lastName) : User(firstName, lastName)
Observe que você deve delegar ao construtor padrão da classe estendida, que é semelhante a chamar o método super()
no construtor de uma nova classe em Java.
Para mais detalhes sobre as aulas, consulte a documentação oficial.
Recurso nº 4: expressões lambda
As expressões lambda, introduzidas com o Java 8, são um de seus recursos favoritos. No entanto, as coisas não são tão brilhantes no Android, pois ele ainda suporta apenas o Java 7 e parece que o Java 8 não será suportado tão cedo. Portanto, soluções alternativas, como Retrolambda, trazem expressões lambda para o Android.
Com Kotlin, não são necessárias bibliotecas ou soluções alternativas adicionais.
Funções em Kotlin
Vamos começar examinando rapidamente a sintaxe da função em Kotlin:
fun add(x: Int, y: Int) : Int { return x + y }
O valor de retorno da função pode ser omitido e, nesse caso, a função retornará Int
. Vale repetir que tudo em Kotlin é um objeto, estendido de Any
, e não há tipos primitivos.
Um argumento da função pode ter um valor padrão, por exemplo:
fun add(x: Int, y: Int = 1) : Int { return x + y; }
Nesse caso, a função add()
pode ser invocada passando apenas o argumento x
. O código Java equivalente seria:
int add(int x) { Return add(x, 1); } int add(int x, int y) { return x + y; }
Outra coisa legal ao chamar uma função é que argumentos nomeados podem ser usados. Por exemplo:
add(y = 12, x = 5)
Para mais detalhes sobre as funções, consulte a documentação oficial.
Usando expressões lambda em Kotlin
As expressões lambda em Kotlin podem ser vistas como funções anônimas em Java, mas com uma sintaxe mais concisa. Como exemplo, vamos mostrar como implementar o listener de cliques em Java e Kotlin.
Em Java:
view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(v.getContext(), "Clicked on view", Toast.LENGTH_SHORT).show(); } };
Em Kotlin:
view.setOnClickListener({ view -> toast("Click") })
Uau! Apenas uma linha de código! Podemos ver que a expressão lambda é cercada por chaves. Os parâmetros são declarados primeiro e o corpo segue o sinal ->
. Com o ouvinte de clique, o tipo do parâmetro de exibição não é especificado, pois pode ser inferido. O corpo é simplesmente uma chamada para a função toast()
para mostrar o toast, que o Kotlin fornece.
Além disso, se os parâmetros não forem usados, podemos deixá-los de fora:
view.setOnClickListener({ toast("Click") })
O Kotlin otimizou as bibliotecas Java e qualquer função que receba uma interface com um método para um argumento pode ser chamada com um argumento de função (em vez de Interface).

Além disso, se a função for o último parâmetro, ela pode ser movida para fora dos parênteses:
view.setOnClickListener() { toast("Click") }
Finalmente, se a função tiver apenas um parâmetro que é uma função, os parênteses podem ser deixados de fora:
view.setOnClickListener { toast("Click") }
Para obter mais informações, consulte o livro Kotlin para desenvolvedores Android de Antonio Leiva e a documentação oficial.
Funções de extensão
Kotlin, semelhante ao C#, oferece a capacidade de estender classes existentes com novas funcionalidades usando funções de extensão. Por exemplo, um método de extensão que calcularia o hash MD5 de uma String
:
fun String.md5(): ByteArray { val digester = MessageDigest.getInstance("MD5") digester.update(this.toByteArray(Charset.defaultCharset())) return digester.digest() }
Observe que o nome da função é precedido pelo nome da classe estendida (neste caso, String
), e que a instância da classe estendida está disponível por meio this
palavra-chave.
As funções de extensão são equivalentes às funções de utilitário Java. A função de exemplo em Java ficaria assim:
public static int toNumber(String instance) { return Integer.valueOf(instance); }
A função de exemplo deve ser colocada em uma classe Utility. O que isso significa é que as funções de extensão não modificam a classe estendida original, mas são uma maneira conveniente de escrever métodos utilitários.
Recurso nº 5: segurança nula
Uma das coisas que você mais apressa em Java é provavelmente NullPointerException
. A segurança nula é um recurso que foi integrado à linguagem Kotlin e é tão implícito que você normalmente não precisa se preocupar. A documentação oficial afirma que as únicas causas possíveis de NullPointerExceptions
são:
- Uma chamada explícita para lançar
NullPointerException
. - Usando o
!!
operador (que explicarei mais tarde). - Código Java externo.
- Se a propriedade
lateinit
for acessada no construtor antes de ser inicializada, umaUninitializedPropertyAccessException
será lançada.
Por padrão, todas as variáveis e propriedades em Kotlin são consideradas non-null
(incapaz de manter um valor null
) se não forem declaradas explicitamente como anuláveis. Como já mencionado, para definir uma variável para aceitar um valor null
, um ponto de interrogação deve ser adicionado após o tipo. Por exemplo:
val number: Int? = null
No entanto, observe que o código a seguir não será compilado:
val number: Int? = null number.toString()
Isso ocorre porque o compilador executa verificações null
. Para compilar, uma verificação null
deve ser adicionada:
val number: Int? = null if(number != null) { number.toString(); }
Este código será compilado com sucesso. O que o Kotlin faz em segundo plano, neste caso, é que o number
se torne nun-null
( Int
em vez de Int?
) dentro do bloco if.
A verificação null
pode ser simplificada usando o operador de chamada segura ( ?.
):
val number: Int? = null number?.toString()
A segunda linha será executada somente se o número não for null
. Você pode até usar o famoso operador Elvis ( ?:
):
val number Int? = null val stringNumber = number?.toString() ?: "Number is null"
Se a expressão à esquerda de ?:
não for null
, ela será avaliada e retornada. Caso contrário, o resultado da expressão à direita é retornado. Outra coisa legal é que você pode usar throw
ou return
no lado direito do operador Elvis, já que são expressões em Kotlin. Por exemplo:
fun sendMailToUser(user: User) { val email = user?.email ?: throw new IllegalArgumentException("User email is null") //... }
O !! Operador
Se você deseja que um NullPointerException
seja lançado da mesma maneira que em Java, você pode fazer isso com o !!
operador. O código a seguir lançará um NullPointerException
:
val number: Int? = null number!!.toString()
Fundição
Casting feito usando uma palavra as
chave as:
val x: String = y as String
Isso é considerado conversão “insegura”, pois lançará ClassCastException
se a conversão não for possível, como Java faz. Existe um operador de conversão “seguro” que retorna o valor null
em vez de lançar uma exceção:
val x: String = y as? String
Para obter mais detalhes sobre a conversão, verifique a seção Type Casts and Casts da documentação oficial e para obter mais detalhes sobre a segurança null
, verifique a seção Null-Safety.
propriedades lateinit
Há um caso em que o uso de propriedades lateinit
pode causar uma exceção semelhante a NullPointerException
. Considere a seguinte classe:
class InitTest { lateinit var s: String; init { val len = this.s.length } }
Este código irá compilar sem aviso. No entanto, assim que uma instância de TestClass
for criada, uma UninitializedPropertyAccessException
será lançada porque a propriedade s
é acessada antes de ser inicializada.
Recurso #6: Função with()
A função with()
é útil e vem com a biblioteca padrão Kotlin. Ele pode ser usado para economizar digitação se você precisar acessar muitas propriedades de um objeto. Por exemplo:
with(helloWorldTextView) { text = "Hello World!" visibility = View.VISIBLE }
Ele recebe um objeto e uma função de extensão como parâmetros. O bloco de código (entre chaves) é uma expressão lambda para a função de extensão do objeto especificado como o primeiro parâmetro.
Recurso #7: Sobrecarga do Operador
Com Kotlin, implementações personalizadas podem ser fornecidas para um conjunto predefinido de operadores. Para implementar um operador, uma função de membro ou uma função de extensão com o nome fornecido deve ser fornecida.
Por exemplo, para implementar o operador de multiplicação, uma função de membro ou função de extensão, com o nome times(argument)
, deve ser fornecida:
operator fun String.times(b: Int): String { val buffer = StringBuffer() for (i in 1..b) { buffer.append(this) } return buffer.toString() }
O exemplo acima mostra uma implementação do operador binário *
na String
. Por exemplo, a seguinte expressão atribuirá o valor “TestTestTestTest” a uma variável newString
:
val newString = "Test" * 4
Como as funções de extensão podem ser usadas, isso significa que o comportamento padrão dos operadores para todos os objetos pode ser alterado. Esta é uma faca de dois gumes e deve ser usada com cautela. Para obter uma lista de nomes de funções para todos os operadores que podem ser sobrecarregados, consulte a documentação oficial.
Outra grande diferença em relação ao Java são os operadores ==
e !=
. Operador ==
se traduz em:
a?.equals(b) ?: b === null
Enquanto o operador !=
se traduz em:
!(a?.equals(b) ?:
O que isso significa é que usar ==
não faz uma verificação de identidade como em Java (compare se as instâncias de um objeto são as mesmas), mas se comporta da mesma maneira que o método equals()
junto com verificações null
.
Para realizar a verificação de identidade, os operadores ===
e !==
devem ser usados no Kotlin.
Recurso nº 8: Propriedades delegadas
Certas propriedades compartilham alguns comportamentos comuns. Por exemplo:
- Propriedades de inicialização lenta que são inicializadas no primeiro acesso.
- Propriedades que implementam Observable no padrão Observer.
- Propriedades que são armazenadas em um mapa em vez de campos separados.
Para tornar casos como este mais fáceis de implementar, Kotlin suporta Propriedades Delegadas :
class SomeClass { var p: String by Delegate() }
Isso significa que as funções getter e setter para a propriedade p
são tratadas por uma instância de outra classe, Delegate
.
Um exemplo de um delegado para a propriedade String
:
class Delegate { operator fun getValue(thisRef: Any?, property: KProperty<*>): String { return "$thisRef, thank you for delegating '${property.name}' to me!" } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { println("$value has been assigned to '${property.name} in $thisRef.'") } }
O exemplo acima imprime uma mensagem quando uma propriedade é atribuída ou lida.
Delegados podem ser criados para propriedades mutáveis ( var
) e somente leitura ( val
).
Para uma propriedade somente leitura, o método getValue
deve ser implementado. São necessários dois parâmetros (retirados da documentação oficial):
- receiver - deve ser o mesmo ou um supertipo do proprietário da propriedade (para propriedades de extensão, é o tipo que está sendo estendido).
- metadados - deve ser do tipo
KProperty<*>
ou seu supertipo.
Esta função deve retornar o mesmo tipo da propriedade, ou seu subtipo.
Para uma propriedade mutável, um delegado deve fornecer adicionalmente uma função chamada setValue
que recebe os seguintes parâmetros:
- receiver - o mesmo que para
getValue()
. - metadados - o mesmo que para
getValue()
. - novo valor - deve ser do mesmo tipo que uma propriedade ou seu supertipo.
Existem alguns delegados padrão que vêm com Kotlin que cobrem as situações mais comuns:
- Preguiçoso
- Observável
- Vetável
Preguiçoso
Lazy é um delegado padrão que usa uma expressão lambda como parâmetro. A expressão lambda passada é executada na primeira vez que o método getValue()
é chamado.
Por padrão, a avaliação de propriedades lentas é sincronizada. Se você não estiver preocupado com multi-threading, você pode usar lazy(LazyThreadSafetyMode.NONE) { … }
para obter desempenho extra.
Observável
O Delegates.observable()
é para propriedades que devem se comportar como Observables no padrão Observer. Ele aceita dois parâmetros, o valor inicial e uma função que possui três argumentos (propriedade, valor antigo e novo valor).
A expressão lambda fornecida será executada toda vez que o método setValue()
for chamado:
class User { var email: String by Delegates.observable("") { prop, old, new -> //handle the change from old to new value } }
Vetável
Esse delegado padrão é um tipo especial de Observable que permite decidir se um novo valor atribuído a uma propriedade será armazenado ou não. Ele pode ser usado para verificar algumas condições antes de atribuir um valor. Assim como Delegates.observable()
, ele aceita dois parâmetros: o valor inicial e uma função.
A diferença é que a função retorna um valor booleano. Se retornar true
, o novo valor atribuído à propriedade será armazenado ou descartado.
var positiveNumber = Delegates.vetoable(0) { d, old, new -> new >= 0 }
O exemplo fornecido armazenará apenas números positivos atribuídos à propriedade.
Para mais detalhes, consulte a documentação oficial.
Recurso #9: Mapeando um Objeto para um Mapa
Um caso de uso comum é armazenar valores das propriedades dentro de um mapa. Isso geralmente acontece em aplicativos que trabalham com APIs RESTful e analisam objetos JSON. Nesse caso, uma instância de mapa pode ser usada como um delegado para uma propriedade delegada. Um exemplo da documentação oficial:
class User(val map: Map<String, Any?>) { val name: String by map val age: Int by map }
Neste exemplo, User
tem um construtor primário que usa um mapa. As duas propriedades pegarão os valores do mapa que são mapeados em chaves que são iguais aos nomes das propriedades:
val user = User(mapOf( "name" to "John Doe", "age" to 25 ))
A propriedade name da nova instância de usuário receberá o valor de “John Doe” e a propriedade age o valor 25.
Isso também funciona para propriedades var em combinação com MutableMap
:
class MutableUser(val map: MutableMap<String, Any?>) { var name: String by map var age: Int by map }
Recurso nº 10: Coleções e Operações Funcionais
Com o suporte para lambdas em Kotlin, as coleções podem ser alavancadas para um novo nível.
Em primeiro lugar, Kotlin distingue entre coleções mutáveis e imutáveis. Por exemplo, existem duas versões da interface Iterable :
- Iterável
- MutávelIterável
O mesmo vale para as interfaces Collection , List , Set e Map .
Por exemplo, any
operação retorna true
se pelo menos um elemento corresponder ao predicado fornecido:
val list = listOf(1, 2, 3, 4, 5, 6) assertTrue(list.any { it % 2 == 0 })
Para obter uma extensa lista de operações funcionais que podem ser feitas em coleções, consulte esta postagem no blog.
Conclusão
Acabamos de arranhar a superfície do que Kotlin oferece. Para os interessados em ler e aprender mais, confira:
- Postagens e livro do blog Kotlin de Antonio Leiva.
- Documentação oficial e tutoriais da JetBrains.
Para resumir, Kotlin oferece a você a capacidade de economizar tempo ao escrever aplicativos Android nativos usando uma sintaxe intuitiva e concisa. Ainda é uma linguagem de programação jovem, mas na minha opinião, agora é estável o suficiente para ser usada na construção de aplicativos de produção.
Os benefícios de usar Kotlin:
- O suporte do Android Studio é perfeito e excelente.
- É fácil converter um projeto Java existente para Kotlin.
- Código Java e Kotlin podem coexistir no mesmo projeto.
- Não há sobrecarga de velocidade no aplicativo.
As desvantagens:
- O Kotlin adicionará suas bibliotecas ao
.apk
gerado, portanto, o tamanho final do.apk
será cerca de 300 KB maior. - Se abusado, a sobrecarga do operador pode levar a um código ilegível.
- IDE e Autocomplete se comportam um pouco mais devagar ao trabalhar com Kotlin do que com projetos Java Android puros.
- Os tempos de compilação podem ser um pouco mais longos.