Kotlin Android, Entendendo e Primeiro Projeto

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes! Você receberá um email de confirmação. Somente depois de confirma-lo é que eu poderei lhe enviar os conteúdos semanais exclusivos. Os artigos em PDF são entregues somente para os inscritos na lista.

Email inválido.
Blog /Android /Kotlin Android, Entendendo e Primeiro Projeto

Kotlin Android, Entendendo e Primeiro Projeto

Vinícius Thiengo
(30281) (8)
Go-ahead
"O método consciente de tentativa e erro é mais bem-sucedido que o planejamento de um gênio isolado."
Peter Skillman
Prototipagem Android
Capa do curso Prototipagem Profissional de Aplicativos
TítuloAndroid: Prototipagem Profissional de Aplicativos
CategoriasAndroid, Design, Protótipo
AutorVinícius Thiengo
Vídeo aulas186
Tempo15 horas
ExercíciosSim
CertificadoSim
Acessar Curso
Quer aprender a programar para Android? Acesse abaixo o curso gratuito no Blog.
Lendo
TítuloManual de DevOps: como obter agilidade, confiabilidade e segurança em organizações tecnológicas
CategoriaEngenharia de Software
Autor(es)Gene Kim, Jez Humble, John Willis, Patrick Debois
EditoraAlta Books
Edição1ª
Ano2018
Páginas464
Conteúdo Exclusivo
Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba gratuitamente conteúdos Android sem precedentes!
Email inválido

Tudo bem?

Neste artigo vamos iniciar os trabalhos com a mais nova linguagem oficial para o dev Android, Kotlin.

Iniciaremos falando um pouco do contexto histórico e técnico e então vamos a apresentação de um projeto Java Android, um aplicativo de palíndromo, e logo depois vamos a transformação desse projeto em um utilizando a nova linguagem.

Desde o início é bom saber que o Kotlin não veio para substituir o Java. Outras linguagens, modernas e tão robustas quanto o Java, já estão no mercado a algum tempo e não conseguiram tomar o lugar do Java como a linguagem de programação mais utilizada, alias esse nunca foi o objetivo de nenhuma delas.

Abaixo os tópicos que estaremos abordando:

O que é e por que Kotlin?

Kotlin é uma ilha russa! Brincadeiras a parte, na verdade é uma linguagem que foi criada em 2011 com o propósito de alavancar as vendas da JetBrains, empresa muito conhecida pelos IDEs que comercializa.

O nome Kotlin realmente é devido a ilha russa, ilha que fica próxima a São Petersburgo, onde se iniciou o projeto da nova linguagem da JetBrains.

O Kotlin foi lançado pela primeira vez, em versão estável, em 2016. Além do propósito de comercialização, a linguagem deveria ter características de linguagens modernas e também ser rápida, um problema da linguagem Scala, por exemplo, que é uma linguagem moderna, mas na compilação é lenta quando comparada ao Java.

Desde 2016 a adoção do Kotlin para desenvolvimento de aplicativos Android veio crescendo consideravelmente. Devido a qualidade da linguagem, rápida adoção da comunidade de desenvolvedores Android. Devido as ferramentas, IDEs, que atendem a ela e também devido ao 100% de interoperabilidade com o Java. Devido a estes a linguagem foi adicionada ao portfólio de linguagens do SO da Google.

Os engenheiros do Google Android anunciaram no Google I/O 17 o Kotlin como a mais nova linguagem oficial da plataforma:

Agora temos: Kotlin, Java e C++. Assim reforçamos que o Kotlin é uma nova linguagem oficial para desenvolvimento de aplicativos Android, não é substituta de nenhuma outra já presente, mesmo que ela realmente tenha inúmeras vantagens em relação as outras.

Principais características

A linguagem é moderna, criada em 2011, então uma menor quantidade de código para as mesmas funcionalidades, quando comparando com algoritmos Java, é algo esperado. Algumas outras características são:

  • Compatível com JDK 6, logo, algoritmos Kotlin são aceitos em qualquer versão do Android;
  • 100% de interoperabilidade com o Java. É possível utilizar código Kotlin em Java e vice versa;
  • Aplicativos Android Kotlin são tão rápidos quanto aplicativos Android Java, podendo ser até mais eficientes;
  • Códigos getters e setters estão presentes de forma implícita, liberando ainda mais espaço para algoritmos mais concisos;
  • A linguagem é type-safe, como o Java, e também null-safe, ou seja, caso precise do valor null em sua lógica de negócio, terá de definir isso de forma explicita;
  • Utiliza cast inteligente e inferência, esse último nos alivia de termos de colocar tipos de dados quando esse é evidente;
  • A linguagem suporta facilmente os paradigmas "Orientação a objetos" e "Funcional";
  • O Android Studio tem 100% de suporte a linguagem.

Essas são algumas das características de destaque, busquei colocar as mais relevantes para você, desenvolvedor Android. As que mais impressionam são: 100% de interoperabilidade com o Java e a possibilidade de ter aplicativos ainda mais eficientes.

Se está com receio de algumas das libraries em uso, em seus projetos, pararem de funcionar, não se preocupe, todas as APIs que rodam no Java rodam também no Kotlin.

Como informado no início do artigo, as características do Kotlin não são tão únicas, muitas já estavam presentes em linguagens como Scala e Groovy, porém as duas características que enfatizamos a pouco fazem da linguagem um facilitador para programadores Android.

Algum aplicativo Android já utiliza essa nova linguagem em produção?

Provavelmente alguns milhares, mas os maiores que a utilizam, e que o uso da linguagem foi publicado, são:

  • Pinterest, com aproximadamente 150 milhões de usuários mensais;
  • Basecamp 3, alias esse utiliza o Kotlin em 100% do projeto;
  • Keepsafe, como Basecamp, também com 100% do código em Kotlin.

Há informes de que algumas empresas de softwares bancários já utilizam o Kotlin em suas bases de código, mas nada ainda divulgado na página oficial da linguagem.

Vale ressaltar que o Kotlin adiciona somente algumas centenas de métodos ao projeto Android e um pouco menos do que 100 KB ao APK final. Com o Proguard em uso é possível diminuir esses números ainda mais.

Exemplo de código

Primeiro, saiba que não é meu objetivo aqui trazer a ti toda a documentação do Kotlin, essa já existe e, apesar de estar em inglês, é pequena e fácil de compreender, pois há muito código simples de exemplo.

O que vou fazer é mostrar a linguagem em uma aplicação real, simples, mas com funcionalidade que permita simular uma em produção.

Porém antes de irmos ao projeto de exemplo do artigo, a seguir apresento um código de uma classe Java que estaria sendo utilizada junto a API Gson, ou seja, esta classe tem de ter os métodos getters e setters de cada variável de instância:

public class Carro {
private String modelo;
private String marca;
private int ano;
private double preco;

public String getModelo() {
return modelo;
}

public void setModelo(String modelo) {
this.modelo = modelo;
}

public String getMarca() {
return marca;
}

public void setMarca(String marca) {
this.marca = marca;
}

public int getAno() {
return ano;
}

public void setAno(int ano) {
this.ano = ano;
}

public double getPreco() {
return preco;
}

public void setPreco(double preco) {
this.preco = preco;
}
}

 

A seguir o código Kotlin da mesma classe, que também poderá ser utilizada junto a API Gson:

class Carro(
var modelo: String,
var marca: String,
var ano: Int,
var preco: Double )

 

Oh Yeah! O que temos acima é a definição da classe Carro com um construtor primário. Os métodos getters e setters, acredite, estão ali, são incluídos de forma implícita.

O var sendo utilizado nos garante esses métodos, pois o var indica: propriedade mutável. A outra opção é val, que indica: propriedade somente de leitura, não mutável.

E as chaves de abertura e fechamento de bloco de classe?

Nem essas são necessárias caso não tenhamos nada de personalizado no corpo da classe.

Note que no Kotlin tudo é objeto, logo, não temos os comuns valores primitivos, tipos básicos, presentes no Java, aqui, apesar do modelo de uso literal de valores do Java ser suportado no Kotlin, podemos invocar métodos e outras propriedades caso existam. O código a seguir é perfeitamente válido:

...
1.toString();
...

 

Os arquivos de classe Kotlin terminam com .kt.

Com isso podemos partir para nosso projeto Java de exemplo e logo depois para os códigos Kotlin dele.

Projeto de exemplo, Android

Nosso projeto de exemplo é um aplicativo, versão alpha, de palíndromo. Um palíndromo é uma palavra ou texto que possa ser lido de trás para a frente e mesmo assim não terá diferença quando comparada a leitura normal, isso quando levando em consideração somente letras, nem mesmo acentuações são consideradas.

Nosso aplicativo de palíndromo é um pouco simples e funciona somente com uma palavra simples de cada vez. Fique tranquilo que mesmo com essa limitação vamos conseguir seguramente mostrar o código também em Kotlin.

Para ter acesso completo ao projeto, digo, incluindo imagens e arquivos de configurações do Android Studio que não é possível colocar aqui, entre no GitHub dele em: https://github.com/viniciusthiengo/palindromo.

Assim, abra o Android Studio e crie um novo projeto, um com uma Empty Activity e com o nome "Palindromo".

Aqui estou utilizando uma versão do Android Studio inferior a versão 3.0 que já vem com a opção de suporte a projetos Kotlin. Mesmo que você esteja com essa versão do Android Studio siga com um projeto Java Android, não marque a opção "Kotlin".

Não utilizei a versão 3.0 do Android Studio, pois até a construção deste artigo ela ainda estava em modo preview.

Ao final desta primeira etapa, projeto em Java Android, teremos o seguinte aplicativo: 

E a seguinte estrutura de projeto:

So, let's code!

Configurações Gradle

Nesta parte inicial, nossa configuração de Gradle Project Level, build.gradle (Project: Palindromo), se mantém como na criação de um novo projeto. Segue:

buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.2'
}
}

allprojects {
repositories {
jcenter()
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}

 

A versão Gradle App Level, build.gradle (Module: app), também mantém as configurações iniciais de um novo projeto, Empty Activity, no Android Studio:

apply plugin: 'com.android.application'

android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "br.com.thiengo.palindromo"
minSdkVersion 10
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
testCompile 'junit:junit:4.12'
}

 

Ambas as versões de Gradle sofrerão atualizações para que seja possível trabalhar com o Kotlin, mas a maior parte destas serão realizadas por um plugin que adicionaremos posteriormente ao IDE.

Configurações AndroidManifest

O AndroidManifest.xml, como os arquivos Gradle, se manterá com a versão inicial, criada a partir de um novo projeto no Android Studio.

Posteriormente, quando na parte Kotlin do artigo, teremos uma pequena atualização para referenciarmos a atividade Kotlin.

Segue configuração:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="br.com.thiengo.palindromo">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">

<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

</application>
</manifest>

Configurações de estilo

Nossos arquivos de configurações de estilo são simples, somente definimos a mais algumas cores e uma imagem de background.

Vamos iniciar com o arquivo de cores, /res/values/colors.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#FFEB3B</color>
<color name="colorPrimaryDark">#FBC02D</color>
<color name="colorAccent">#FFC107</color>
</resources>

 

Assim o arquivo de String, /res/values/colors.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Palíndromo</string>
</resources>

 

Por fim o arquivo de definição de estilo, /res/values/styles.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light">
<item name="android:windowBackground">@drawable/background</item>

<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>

Classe de domínio

No pacote /domain de nosso projeto teremos somente uma classe, Palindromo:

public class Palindromo {
private String conteudo;

public Palindromo( String c ){
this.conteudo = c;
}

public boolean ehPalindromo(){
String invertido = new StringBuilder( conteudo ).reverse().toString();

return invertido.equalsIgnoreCase(conteudo);
}

public String getConteudo(){
return conteudo.toLowerCase();
}
}

 

Para que a atividade principal não tivesse ainda mais responsabilidades, foi uma melhor escolha encapsular todo o código de verificação de palíndromo em uma classe única. Por isso o uso de uma classe de domínio.

Atividade principal

A atividade principal é tão simples quanto nossa única classe de domínio. Vamos iniciar com o layout, /res/layout/activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
tools:context="br.com.thiengo.palindromo.MainActivity">

<TextView
android:id="@+id/tv_titulo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginBottom="24dp"
android:layout_marginTop="32dp"
android:gravity="center"
android:text="É um palíndromo? (versão beta, somente palavras)"
android:textColor="#ddd"
android:textSize="24sp" />

<EditText
android:id="@+id/et_palindromo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_titulo"
android:layout_marginBottom="8dp"
android:hint="Informe aqui a palavra"
android:textColor="#ddd"
android:textColorHint="#888" />

<TextView
android:id="@+id/tv_resposta"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/et_palindromo"
android:layout_marginTop="8dp"
android:textColor="#ddd"
android:textSize="18sp" />

<Button
android:id="@+id/bt_verificar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#306271"
android:text="Verificar"
android:textColor="#ddd" />
</RelativeLayout>

 

A seguir o diagrama do layout anterior:

E então o código Java de MainActivity:

public class MainActivity extends AppCompatActivity
implements View.OnClickListener {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Button btVerificar = (Button) findViewById(R.id.bt_verificar);
btVerificar.setOnClickListener( this );
}

@Override
public void onClick(View view) {
EditText etPalindromo = (EditText) findViewById(R.id.et_palindromo);
TextView tvResposta = (TextView) findViewById(R.id.tv_resposta);
Palindromo palindromo = new Palindromo( etPalindromo.getText().toString() );
String resposta;

if( palindromo.ehPalindromo() ){
resposta = " é um palíndromo";
}
else{
resposta = " NÃO é um palíndromo";
}
resposta = palindromo.getConteudo() + resposta;
tvResposta.setText( resposta );
}
}

 

Note que mesmo o código sendo pequeno, com o Kotlin conseguiremos ainda menos linhas sem perder a qualidade na compreensão dos algoritmos.

Atualizando o aplicativo para um projeto Kotlin

Saiba que caso você esteja com o Android Studio 3.0 ou superior, não precisará do passo inicial desta seção: "Instalação do plugin Kotlin". Isso, pois você terá a opção de já iniciar com o projeto Kotlin desde a criação dele, o Kotlin já vem configurado a partir do Android Studio Canary:

Esse plugin, que é preciso instalar para versões anteriores ao AS 3.0, nos permite ter, no IDE, algumas ferramentas exclusivas para projetos Kotlin, incluindo a mais indicada e provavelmente a mais utilizada: conversão de código Java para código Kotlin.

Com esse plugin também será possível verificar a versão Java do código Kotlin em trabalho. Acredite, utilizaremos essa ferramenta de verificação de versão Java com frequência agora no início dos estudos, aqui no Blog, desta nova linguagem.

Instalação do plugin Kotlin

Em sua instalação do Android Studio, mais precisamente no menu, clique em "Preferences":

Logo depois cliquem em "Plugins" e então clique em "Install JetBrains plugin...":

Na caixa de busca digite "Kotlin". Então selecione a opção que tem no rótulo somente "Kotlin" e assim clique em "Install":

Logo depois da instalação você terá a opção de reiniciar o IDE, clique nesta opção.

Atualização Gradle

Com seu projeto aberto no Android Studio, vá em "Tools", logo depois acesse "Kotlin" e então clique em "Configure Kotlin in Project": 

Escolha a opção "Android with Gradle":

Então, no dialog aberto, apenas certifique-se de que "Kotlin compiler and runtime version" esteja referenciando a versão mais atual:

Assim seu Gradle Project Level, build.gradle (Project: Palindromo), agora terá a seguinte nova configuração:

buildscript {
ext.kotlin_version = '1.1.2-4'
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

allprojects {
repositories {
jcenter()
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}

 

E então o Gradle App Level, build.gradle (Module: app):

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'

android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "br.com.thiengo.palindromo"
minSdkVersion 10
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
testCompile 'junit:junit:4.12'
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
}
repositories {
mavenCentral()
}

 

Antes de sincronizar o projeto, no Gradle App Level adicione a seguinte linha em destaque:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
...

 

O 'kotlin-android-extensions' vai nos permitir um acesso simplificado as Views de nosso layout, sem necessidade do uso de findViewById().

Por fim, sincronize o projeto.

Classe de domínio com código Kotlin

Ao invés de atualizarmos a classe Java Palindromo para utilizar códigos Kotlin, vamos criar uma nova. No package /domain clique com o botão direito nele, vá em "New" logo depois clique em "Kotlin File / Class". Como nome coloque "PalindromoK", então selecione "Class" e clique em "Ok":

Você terá um código como o a seguir:

class PalindromoK {
/* TODO */
}

 

Essa já é a definição de uma classe Kotlin, muito próximo ao que temos em Java.

O que precisamos agora é definir uma variável de instância, de rótulo conteudo, privada e do tipo String, em seguida inicializa-la com o um parâmetro do construtor.

No Kotlin as variáveis de instâncias são conhecidas como propriedades e podem ser mutáveis ou não-mutáveis.

Antes de prosseguir saiba que não poderíamos continuar utilizando o rótulo Palindromo para a nova classe Kotlin, isso, pois classes Java e Kotlin têm conflitos de nomes entre elas quando no mesmo pacote.

Agora vamos a atualização em PalindromoK, atualização que corresponde ao construtor de Palindromo e inicialização da propriedade conteudo:

class PalindromoK constructor( conteudo: String ) {

val conteudo: String = conteudo
get(){
return field.toLowerCase();
}
}

 

A seguir a estrutura de definição de uma propriedade em Kotlin:

var <nomeDaPropriedade>[: <TipoDaPropriedade>] [= <InicializadorDaPropriedade>]
[<getter>]
[<setter>]

 

Quando utilizando o var, os métodos getter e setter já estão presentes, mesmo que não sejam apresentados explicitamente em código. Podemos modifica-los para atender ao nosso domínio do problema.

TipoDaPropriedade pode ser opcional quando é possível inferir o tipo de dado a partir de um InicializadorDaPropriedade ou a partir do método get() sendo utilizado para inicialização da propriedade.

Em nosso caso, TipoDaPropriedade é obrigatório, pois estamos utilizando um construtor primário com um parâmetro que na verdade não representa uma propriedade, ele é somente utilizado para inicializar a propriedade.

Ou seja, o parâmetro conteudo de constructor( conteudo: String ) somente pode ser utilizado para inicializar a propriedade como estamos fazendo ou em um bloco de inicialização, como a seguir:

...
val conteudo: String;

init{
this.conteudo = conteudo;
}
...

 

Note que o código anterior é somente um exemplo, pois vamos manter o uso do primeiro modelo de inicialização de propriedade apresentado, utilizando o parâmetro do construtor primário.

Ok, você informou a estrutura do var, mas estamos com o val. Como seria a estrutura deste tipo de propriedade?

Muito similar. O var tem get e set, pois é a definição de uma propriedade mutável. A estrutura de uma propriedade val somente não tem o método set, pois é a definição de uma propriedade não-mutável:

val <nomeDaPropriedade>[: <tipoDaPropriedade>] [= <inicializadorDaPropriedade>]
[<getter>]

 

A maneira como definimos o get() é uma para que seja possível personaliza-lo. Fique ciente sobre essa parte da sintaxe, pois o método get() já existe e é do tipo final, ou seja, um override não funcionaria.

A palavra-chave field nos permite acesso a propriedade referente ao get(). Essa é uma particularidade do Kotlin, conhecida como backing field (campo / propriedade de apoio). Como programadores Java, provavelmente a primeira coisa que faríamos neste caso seria algo como:

...
get(){
return this.conteudo.toLowerCase();
}
...

 

Neste caso não poderíamos utilizar nosso parâmetro de construtor, conteudo, como inicializador de nossa propriedade conteudo, não como estamos fazendo atualmente.

Algo a se notar é que os ";", ponto e vírgula, são opcionais. Em alguns pontos do projeto o utilizaremos e em outros não, deixando isso em evidência.

E o tipo de retorno do get(), não é necessário defini-lo?

Para o get(), não. Pois já é conhecido o tipo devido a definição da propriedade, mesmo quando esse é por inferência.

Ok, mas e os modificadores de acesso (public, private e protected)? Não tem algum presente no código da classe.

Na verdade estão sim presentes, porém de forma implícita. Por padrão todas as propriedades são private, mas os métodos get() e set() delas são public. Você pode explicitamente alterar os modificadores de acesso.

Agora o que nos resta é a criação do método ehPalindromo():

class PalindromoK constructor( conteudo: String ) {
...

fun ehPalindromo() : Boolean {
return conteudo == conteudo.reversed();
}
}

 

Simples, certo? Com o Kotlin podemos utilizar a verificação de igualdade de objetos com o == sem problemas, digo, quando a classe é um data class. Com este tipo de classe o == invoca, implicitamente, o uso do equals().

Uma data class é uma classe que existe com o objetivo de ser host de dados, somente armazena-los enquanto o algoritmo está em execução. Em nosso caso, a comparação está sendo realizada com dados do tipo String.

Se fosse necessária a comparação de objetos do tipo PalindromoK em nossa lógica de negócio, deveríamos realizar a seguinte atualização nesta classe para obter essa característica de igualdade (além de outras):

data class PalindromoK constructor( private val _conteudo: String ) {
val conteudo: String = _conteudo
get(){
return field.toLowerCase();
}

fun ehPalindromo() : Boolean {
return conteudo == conteudo.toString().reversed();
}
}

 

É isso mesmo que notou. Devido a algumas regras de negócio da linguagem foram necessárias mais atualizações além da adição de data ao cabeçalho da classe. Por exemplo: se com o construtor primário em uso, tem de haver propriedade, por isso o uso de val (poderia ser var) e o renomeamento de conteudo para _conteudo, esse último para evitar conflito com a propriedade pública: conteudo.

Note que todas as definições apresentadas aqui: construtor, declaração de propriedade e declaração de função. Todas elas têm mais variantes. A documentação cobre cada uma delas de maneira simples.

As definições de package e de import, incluindo os já padrões adicionados aos arquivos Kotlin, todas essas são como no Java.

Por fim temos uma nova classe com apenas 10 linhas de código contra 16 linhas de código da classe Palindromo Java. É pouco coisa, mas tenha em mente que nossa classe Java já era muito simples e mesmo assim foi possível diminui-la sem perder qualidade na leitura e entendimento do algoritmo.

Note que como nosso construtor não tem nenhuma anotação e nem mesmo a definição explícita de um modificador de acesso, nós podemos seguramente remover a palavra constructor, pois neste caso ela é opcional:

class PalindromoK( conteudo: String ) {
val conteudo: String = conteudo
get(){
return field.toLowerCase();
}

fun ehPalindromo() : Boolean {
return conteudo == conteudo.reversed();
}
}

 

Um outro caminho para conversão de classes Java para classes Kotlin

Como informado no início da seção de trabalho com o Kotlin, podemos optar por um caminho trivial de conversão, sem necessidade de irmos passo a passo construindo o código equivalente em uma classe Kotlin.

Somente para teste, crie no package /domain uma nova classe Java, Carro:

public class Carro {
private String modelo;
private String marca;
private int ano;
private double preco;

public String getModelo() {
return modelo;
}

public void setModelo(String modelo) {
this.modelo = modelo;
}

public String getMarca() {
return marca;
}

public void setMarca(String marca) {
this.marca = marca;
}

public int getAno() {
return ano;
}

public void setAno(int ano) {
this.ano = ano;
}

public double getPreco() {
return preco;
}

public void setPreco(double preco) {
this.preco = preco;
}
}

 

Deixe ela aberta no IDE e em seguida acesse "Code", no menu do Android Studio, e então clique em "Convert Java File to Kotlin File":

Logo depois o IDE vai informar que alguns códigos do projeto poderão ter de passar por atualizações depois da conversão e se você deseja que o IDE faça essas correções para ti. Aqui vamos escolher que "Ok":

Assim teremos a seguinte nova classe:

class Carro {
var modelo: String? = null
var marca: String? = null
var ano: Int = 0
var preco: Double = 0.toDouble()
}

 

Esta representa exatamente a classe Java que tínhamos anteriormente. Digo "tínhamos", pois a versão Java é literalmente substituída pela versão Kotlin quando a conversão é realizada desta maneira.

Até o final do projeto de exemplo vamos seguir com as conversões passo a passo, assim é melhor para discutirmos as particularidades da linguagem.

Versão Java da classe Kotlin, PalindromoK

É possível aplicar o "Decompile" em nosso código Kotlin para visualizar a versão dele em Java.

Com a classe PalindromoK aberta no Android Studio, vá em "Tools", depois em "Kotlin" e por fim clique em "Show Kotlin Bytecode":

Clique em "Decompile" e assim terá a versão Java do código:

@Metadata(
mv = {1, 1, 6},
bv = {1, 0, 1},
k = 1,
d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\u000e\n\u0002\b\u0004\n\u0002\u0010\u000b\n\u0000\u0018\u00002\u00020\u0001B\r\u0012\u0006\u0010\u0002\u001a\u00020\u0003¢\u0006\u0002\u0010\u0004J\u0006\u0010\u0007\u001a\u00020\bR\u0013\u0010\u0002\u001a\u00020\u00038F¢\u0006\b\n\u0000\u001a\u0004\b\u0005\u0010\u0006¨\u0006\t"},
d2 = {"Lbr/com/thiengo/palindromo/domain/PalindromoK;", "", "conteudo", "", "(Ljava/lang/String;)V", "getConteudo", "()Ljava/lang/String;", "ehPalindromo", "", "production sources for module app"}
)
public final class PalindromoK {
@NotNull
private final String conteudo;

@NotNull
public final String getConteudo() {
String var1 = this.conteudo;
if(var1 == null) {
throw new TypeCastException("null cannot be cast to non-null type java.lang.String");
} else {
String var10000 = var1.toLowerCase();
Intrinsics.checkExpressionValueIsNotNull(var10000, "(this as java.lang.String).toLowerCase()");
return var10000;
}
}

public final boolean ehPalindromo() {
String var1;
String var2 = var1 = this.getConteudo();
if(var1 == null) {
throw new TypeCastException("null cannot be cast to non-null type kotlin.CharSequence");
} else {
String var3 = StringsKt.reversed((CharSequence)var1).toString();
return Intrinsics.areEqual(var2, var3);
}
}

public PalindromoK(@NotNull String conteudo) {
Intrinsics.checkParameterIsNotNull(conteudo, "conteudo");
super();
this.conteudo = conteudo;
}
}

 

Muito diferente de nossa versão Java, certo? Alias, essa é uma maneira de estudar o Kotlin, digo, se você também for programador Java. Veja o que a definição val em nossa propriedade conteudo realmente significa em Java:

...
@NotNull
private final String conteudo;
...

 

A entidade é final, como informado anteriormente, somente pode ter uma única atribuição a ela.

Como o Kotlin é null-safe, para que seja possível trabalharmos com valores null, temos de definir isso de maneira explícita, logo depois do tipo da propriedade temos de colocar um ?:

...
val conteudo: String?
...

 

Uma definição como a anterior remove a anotação @NotNull da versão Java da classe. Porém note que em nosso código, devido ao trabalho com null, alguns outros trechos deveriam ser alterados. Digo deveriam, pois vamos seguir com a versão null-safe.

Uma maneira de utilizar a classe PalindromoK com possibilidade de valor null na propriedade conteudo seria:

class PalindromoK constructor( conteudo: String ) {
val conteudo: String? = conteudo
get(){
/*
* if() TAMBÉM PODE SER UMA EXPRESSÃO NO KOTLIN,
* MAS NESTE CASO PRECISA SER SEGUIDO PELO else.
* */
field = if( field != null )
field
else
"";

return field.toLowerCase();
}

fun ehPalindromo() : Boolean {
val status = if(conteudo != null)
conteudo == conteudo.toString().reversed()
else
false;
return status;
}
}

 

Como informado, vamos seguir com a versão null-safe, o código acima é somente uma possibilidade de trabalhar o nosso PalindromoK podendo ter o valor null.

Teste com classe Kotlin em código Java

Agora vamos a uma pequena alteração para que seja possível visualizar, mesmo que parcialmente, o 100% de interoperabilidade entre Kotlin e Java.

Na MainActivity do projeto realize a seguinte atualização:

...
@Override
public void onClick(View view) {
EditText etPalindromo = (EditText) findViewById(R.id.et_palindromo);
TextView tvResposta = (TextView) findViewById(R.id.tv_resposta);
PalindromoK palindromo = new PalindromoK( etPalindromo.getText().toString() );
...
}
...

 

Executando o aplicativo e testando uma palavra qualquer para palíndromo, temos: 

Assim podemos ir a criação da atividade principal em Kotlin code.

Criando a atividade principal com código Kotlin

Para a atividade principal vamos manter o layout XML, somente vamos criar uma nova classe.

Como fizemos anteriormente, vá a raiz do projeto, digo, no mesmo package onde se encontra a classe MainActivity, e crie uma classe Kotlin com o nome MainActivityK:

class MainActivityK {
/* TODO */
}

 

O que primeiro que precisamos é a herança de AppCompatActivity e a sobrescrita do método onCreate():

class MainActivityK : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}

 

Foi possível sobrescrever o método onCreate() de AppCompatActivity porque ele é um método open, ou seja, não é definido como final (definição padrão para funções concretas) e assim podemos criar nossas próprias versões quando em subclasses.

A herança é como segue: quando ela vem de uma classe concreta, na verdade temos de colocar a sintaxe de criação de instância e não somente o nome da classe. Note que para criarmos uma instância no Kotlin nós não utilizamos a palavra-chave new.

O parâmetro savedInstanceState, como no código Java, pode ser null, por isso o tipo Bundle seguido de ?.

Agora precisamos do código de implementação da Interface OnClickListener:

class MainActivityK :
AppCompatActivity(),
View.OnClickListener {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}

override fun onClick(view: View?) {
/* TODO */
}
}

 

Veja que a definição de implementação de Interface vem na mesma parte da definição de herança de classe, porém a sintaxe é distinta, não temos de criar uma instância. Essa área é conhecida como "lista de supertipos".

Em Kotlin, toda Interface tem por padrão os métodos, funções, sendo open, podendo ser sobrescritos em subclasses.

Podemos ter herança múltipla como no C++?

Não, apesar da lista de supertipos induzir a isso, no Kotlin a herança direta é como no Java: quando vinda de classe, somente uma é permitida.

Com isso podemos partir para a adição do listener de clique ao Button de nosso layout:

class MainActivityK :
AppCompatActivity(),
View.OnClickListener {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

bt_verificar.setOnClickListener(this)
}

override fun onClick(view: View?) {
/* TODO */
}
}

 

Lembra do apply plugin: 'kotlin-android-extensions' adicionado ao Gradle App Level? Devido a ele podemos acessar facilmente um objeto da camada de visualização, sem necessidade do findViewById(), apenas utilizando o ID da View.

Assim o que nos resta é o código de verificação de palíndromo que deve vir em onClick().

class MainActivityK :
AppCompatActivity(),
View.OnClickListener {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

bt_verificar.setOnClickListener( this )
}

override fun onClick(view: View?) {
val palindromo = PalindromoK( et_palindromo.text.toString() )
var resposta: String

resposta = if( palindromo.ehPalindromo() )
" é um palíndromo"
else
" NÃO é um palíndromo"

resposta = palindromo.conteudo + resposta
tv_resposta.text = resposta
}
}

 

Veja que em val palindromo não precisamos de definir o tipo da entidade, pois o Kotlin, por inferência, sabe que o tipo é PalindromoK. Também seguramente podemos utilizar val em palindromo, pois ele não terá outra atribuição dentro do escopo da função onClick().

Novamente utilizando o if...else como expressão. Nesta parte a sintaxe substitui um operador ternário que estaríamos utilizando se o código fosse em Java, esse operador não existe no Kotlin.

Assim finalizamos a atividade principal em Kotlin, podemos partir para os testes.

Atualizando o AndroidManifest

Antes de irmos aos testes, precisamos mudar a referência de atividade no AndroidManifest.xml, vamos apontar para a nova classe MainActivityK:

<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="br.com.thiengo.palindromo">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">

<activity android:name=".MainActivityK">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

Testes e resultados

No Android Studio, já com o emulador ou device de testes preparado, vá em "Build", depois clique em "Rebuild Project". Logo depois do rebuild execute o aplicativo.

Testando a palavra "reviver", temos:

Agora testando a palavra "casa", temos:

Assim temos nosso primeiro projeto em Kotlin, ainda conciso e com um menor número de linhas, mesmo já tendo um projeto Java bem simples.

Obviamente que esse foi apenas um simples projeto, as possibilidades com o Kotlin são no mínimo as mesmas que com o Java ou C++.

Estendendo classes para otimizar o código

Não necessariamente estender uma classe vai otimizar seu código Kotlin, mas em nosso caso podemos até mesmo descartar a classe PalindromoK utilizando uma característica de destaque do Kotlin: a fácil possibilidade de extensão de classes.

Em nosso caso, na classe MainActivityK, adicione o seguinte novo código para estender a classe String:

fun String.ehPalindromo(): String{
return if(this.toLowerCase().reversed() == this.toLowerCase())
"${this.toLowerCase()} é um palíndromo"
else
"${this.toLowerCase()} NÃO é um palíndromo"
}

class MainActivityK :
AppCompatActivity(),
View.OnClickListener {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

bt_verificar.setOnClickListener( this )
}

override fun onClick(view: View?) {
tv_resposta.text = et_palindromo.text.toString().ehPalindromo()
}
}

 

What?

Isso mesmo, não mais precisamos da classe PalindromoK. A funcionalidade de ehPalindromo() se encaixa perfeitamente ao contexto de responsabilidades da classe String, não há problemas nem mesmo de perda de código conciso neste caso.

Note o ${this.toLowerCase()} entre as aspas duplas de String. Essa é uma outra facilidade provida no Kotlin em relação ao Java. Podemos colocar expressões ou somente as propriedades puras dentro de literais de String para serem processadas. Se você é desenvolvedor PHP deve ter se identificado bastante com essa características!

Mas espere um pouco, a extensão de String, ehPalindromo(), está fora de um escopo de classe, isso é possível?

Sim. Podemos criar funções fora de classes, Kotlin é uma linguagem que não da suporte somente a orientação a objetos. Mas note que essa característica deve ser utilizada com bom senso, pois ter um código menor não necessariamente significa código mais eficiente e legível.

Assim, depois desta última atualização, conseguimos um código Kotlin com um total de 23 linhas, mantendo a fácil compreensão e ainda eficaz. O código Java tinha um total de 48 linhas.  

Aqui no Blog e canal vamos prosseguir trabalhando também com essa nova linguagem, principalmente devido ao aumento de produtividade que ela pode nos trazer. Logo, não se esqueça de se inscrever na lista de emails (logo ao lado, ou abaixo) para receber os conteúdos em primeira mão.

Se inscreva também no canal: Thiengo [Calopsita].

Vídeo com implementação passo a passo do projeto

A seguir o vídeo com a implementação do projeto Kotlin de exemplo:

Para acesso ao conteúdo completo do projeto, entre no seguinte GitHub dele em: https://github.com/viniciusthiengo/palindromo.

Conclusão

Kotlin é moderno e com ele conseguimos sim o aumento da produção no desenvolvimento de aplicativos, mas antes desse aumento temos de ter em mente a curva de aprendizagem.

Não somente o estudo completo da documentação vai nos ajudar a entender a linguagem nos "por menores", mas também a prática para adquirir o precioso conhecimento tácito.

Ok, mas já sou um desenvolvedor Java especialista. Tenho em mente alguns projetos complexos. Devo, mesmo assim, partir para o Kotlin?

Se o tempo não é o bastante, eu seguramente indico que você foque em ao menos um de seus projetos complexos antes de iniciar os estudos do Kotlin. De preferência o de provável mais impacto.

Adiar mais uma vez um projeto mesmo sabendo que o que você já tem em mãos (conhecimento do Java) é o suficiente para construí-lo, isso na verdade é desculpa para não desenvolve-lo.

Mas de forma alguma recomendo descartar o Kotlin, como já mencionado em vários pontos do artigo: o aumento de produção é evidente quando você tem o conhecimento pleno da linguagem.

Se estiver com um tempo sobrando entre a correria do dia a dia e o desenvolvimento de seu projeto, não deixe de ao menos ir lendo e testando os pequenos algoritmos da documentação do Kotlin.

Apesar de nem mesmo no longo prazo eu enxergar o Java perdendo a posição de linguagem de programação mais utilizada, vejo o Kotlin se destacando como a principal linguagem para construção de aplicativos modernos.

Não esqueça de se inscrever na lista de emails do Blog para obter os conteúdos exclusivos em primeira mão.

Caso tenha dúvidas, críticas ou dicas, não deixa de comenta-las logo abaixo.

Abraço.

Fontes

Android Announces Support for Kotlin

Kotlin and Android

Get Started with Kotlin on Android

Kotlin on Android FAQ

Resources to Learn Kotlin

Kotlin.org, página oficial da linguagem

Kotlin Reference

Why Kotlin?

Kotlin: uncovered - Part 1

Kotlin: uncovered - Part 2

Kotlin: uncovered - Part 3

Why you should totally switch to Kotlin

Wikipedia: Kotlin (programming language)

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes!
Email inválido

Relacionado

Proguard AndroidProguard AndroidAndroid
MVP AndroidMVP AndroidAndroid
Construindo a Política de Privacidade de Seu Aplicativo Android [Agora Obrigatório]Construindo a Política de Privacidade de Seu Aplicativo Android [Agora Obrigatório]Android
FCM Android - Domínio do Problema, Implementação e Testes Com Servidor de Aplicativo [Parte 1]FCM Android - Domínio do Problema, Implementação e Testes Com Servidor de Aplicativo [Parte 1]Android

Compartilhar

Comentários Facebook

Comentários Blog (8)

Para código / script, coloque entre [code] e [/code] para receber marcação especifica.
Forneça seu nome válido.
Forneça seu email válido.
Forneça o comentário.
Enviando, aguarde...
Thyago Neves Silvestre (1) (0)
04/06/2021
Bom dia Thiengo, tudo bem? Comecei a ler o livro"Programming Koltin" de Stephen Samuel e Stefan Bocutiu, mas vi que é de 2017. Você sabe dizer se já está desatualizado ou se ainda compensa a leitura? Caso esteja, se puder indicar outro ficaria grato.
Responder
Vinícius Thiengo (0) (0)
05/06/2021
Thyago, tudo bem?

Compensa sim a leitura.

As características de linguagem apresentadas certamente são praticamente as mesmas.

O problema da "data da publicação do livro" é mais quando o livro é sobre ferramentas especificas do Android.

Pois pode ser que algumas bibliotecas muito utilizadas no conteúdo do livro não mais estejam disponível nas versões mais recentes do Android.

Mas em relação ao Kotlin... pode investir com segurança no título porque será sim tão útil quanto se você estivesse comprando e lendo em 2017.

Thyago, é isso.

Abraço.
Responder
28/11/2018
Qual melhor para trabalhar com kotlin: Intellij idea ou Android Studio 3 ?
Responder
Vinícius Thiengo (1) (0)
30/11/2018
Ewerton, tudo bem?

Para trabalho com o Kotlin, fora do contexto Android, a melhor escolha é o IntelliJ IDEA:

https://www.jetbrains.com/idea/download

Em contexto Android, escolha o Android Studio: https://www.thiengo.com.br/android-studio-instalacao-configuracao-e-otimizacao

Abraço.
Responder
Robson (1) (0)
30/12/2017
Olá Thiengo boa tarde, cara o AS 3 já ta ai e já existe a 3.1 eu ainda não baixei por conta do Kotlin como sabemos é a linguagem oficial e eu não procurei saber nada sobre ela, queria saber se posso usar a nova IDE e continuar com o java e sera que vai ter problemas com projetos feitos na 2.3.2? eu preciso configurar algo para continuar com java?
Sei como vc mesmo já explicou que Kotlin ira dominar mais agora não tenho nem como abraçar outra linguagem.
Obrigado.
Responder
Vinícius Thiengo (3) (0)
30/12/2017
Robson, tudo bem?

Pode migrar sem receios para a versão estável mais atual do Android Studio, versão 3.0. O máximo que você terá de fazer é atualizar a versão do Gradle que está utilizando atualmente em seus projetos Java.

Note que o Kotlin é a mais nova linguagem oficial do Android e não a única. O Java, C++ e C continuam sendo também linguagens oficiais e o Android Studio, mesmo nas versões mais atuais, dá sim suporte ao Java, alias: é o Kotlin que é opcional.

O domínio do Kotlin, uma aposta que eu faço, virá no médio / longo (este último é o mais provável).

Abraço.
Responder
29/07/2017
Fala Thiengo, blz ?
Acompanho sempre você, me ajuda muito, venho agradecer e pedir uma ajuda.
Estou a começar a desenvolver um app, e preciso gerencia-lo remotamente via web service por um site próprio. Desculpe ser leigo no assunto, mas, gostaria que me indicasse q tipo de procedimentos seguir para a construção desse app, em q eu gerencie o app por um site e mande notificações para os clientes.
Mais uma vez muito obrigado.
Abraços.
Responder
Vinícius Thiengo (1) (0)
30/07/2017
Andre, tudo bem?

Você precisará primeiro conectar o aplicativo, para ele consumir dados, ao backend Web de seu projeto. Depois terá de entregar um sistema de notificação push ao seu sistema.

Ao invés de explicar passo a passo o que fazer, recomendo que veja todo o conteúdo do link a seguir: http://www.thiengo.com.br/fcm-android-dominio-do-problema-implementacao-e-testes-com-servidor-de-aplicativo-parte-1

O foco principal dele é o uso da API FCM de notificação push, mas, no artigo em texto, construo passo a passo um aplicativo que consome dados de um backend Web e esse gerencia o conteúdo do app Android além de trabalhar com notificações para apresentar novos conteúdos.

O conteúdo do link informado é exatamente o que você está buscando, obviamente que terá de alterar algumas coisas se quiser reaproveitar o código. Mas não deixe de estuda-lo, pois tentar reutilizar diretamente não vai lhe ajudar, é preciso entende-lo.

O restante do conteúdo, caso queira se aprofundar ainda mais no aplicativo e no sistema de notificação, está nos links a seguir:

http://www.thiengo.com.br/fcm-android-relatorio-e-notificacao-por-topicos-parte-2
http://www.thiengo.com.br/fcm-android-notificacao-personalizada-com-notificationcompat-parte-3

Abraço.
Responder