Se você ainda não conhece as motivações deste projeto, leia o primeiro artigo aqui.

Olá pessoal! No último post, configuramos o CircleCI para observar as branches do nosso projeto, bem como a abertura de pull requests no repositório. Hoje, vamos olhar um pouco mais o projeto e começar a estruturá-lo para posteriormente iniciarmos a implementação de fato.

O projeto em si foi criado a partir do template padrão do Android Studio 3.0.1, sem qualquer modificação na sua estrutura, e sem a inclusão do Kotlin por padrão. Meu intuito é entendermos o que é necessário para transformarmos um projeto Android com Java em um projeto Android com Kotlin.

O primeiro passo aqui é ajustar o arquivo build.gradle principal, aquele localizado na raiz do projeto. Inicialmente, vamos remover os comentários vindos do template. Eles são informativos sobre como configurar as dependências do projeto, porém podemos removê-los tranquilamente, já que sabemos onde vamos colocar cada coisa.

Em seguida, vamos criar uma variável, chamada de kotlinVersion, para guardar a versão do Kotlin que estaremos utilizando no projeto. É importante que essa versão esteja separada, pois ela deve ser a mesma em todas as dependências relacionadas ao Kotlin no projeto. Aqui fica uma ressalva: perceba que utilizamos a nomenclatura com Camel Case (enquanto o template do AS para Kotlin utiliza Snake Case). O Groovy (linguagem utilizada nos scripts do Gradle) tem convenções de código muito semelhantes ao Java. Assim, utilizamos Snake Case apenas nos casos onde o valor é uma constante, e sempre em caixa alta.

Após isso, adicionamos o plugin de Kotlin para Gradle, fazendo uso da interpolação de strings para inserir a versão. Assim, nosso arquivo build.gradle ficará assim:

buildscript {

  ext.kotlinVersion = '1.2.30'

  repositories {
    google()
    jcenter()
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:3.0.1'
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
  }
}

allprojects {
  repositories {
    google()
    jcenter()
  }
}

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

Vamos agora editar então o arquivo de build do módulo app (localizado em app/build.gradle). Nele, primeiramente aplicamos o plugin do Kotlin, seguindo a nomenclatura mais recomendada pelo Gradle - utilizando o namespace. Dessa forma, aplicamos o plugin org.jetbrains.kotlin.android. Em seguida, vamos atualizar o tooling para a última versão do Android (atualmente a API 27). Como o Android Studio 3.0 já foi lançado a algum tempo, o seu template padrão ainda aponta para a API 26. Assim, apontamos as versões de compileSdkVersiontargetSdkVersion para 27, além de atualizarmos a versão da Support Library para 27.1.0, a versão mais recente neste momento.

O próximo passo para completar a integração do Kotlin no projeto é a adição da standard library do Kotlin. Essa dependência possui 3 versões: kotlin-stdlib (Java 6), kotlin-stdlib-jre7 (Java 7) e kotlin-stdlib-jre8 (Java 8). Particularmente eu adiciono a versão jre7, primeiro pelo fato da nossa API mínima ser KitKat (que já suporta as features do Java 7). Poderíamos utilizar a jre8, porém isso faria com que o processo de desugaring ocorresse durante a compilação, o que pode impactar no nosso tempo de build.

Por fim, dois pontos de ajuste que particularmente recomendo por questões de organização. O primeiro é a adição de source sets específicos para Kotlin. Quando temos um projeto Java, os arquivos fonte geralmente ficam na pasta src/main/java. Assim, adicionamos aos source sets src/main/kotlin. Ao meu ver, essa organização é particularmente útil quando o projeto acaba tendo arquivos de ambas as linguagens (o que não deve ocorrer no nosso caso) e para que a estrutura de diretórios fique mais semântica. O segundo ponto de ajuste, mais estético, é a padronização do uso de aspas simples e duplas no arquivo. Aspas duplas, somente quando houver interpolação na string.

Nosso arquivo, então, fica dessa forma:

apply plugin: 'com.android.application'
apply plugin: 'org.jetbrains.kotlin.android'

android {
  compileSdkVersion 27

  defaultConfig {
    applicationId 'net.rafaeltoledo.social'
    minSdkVersion 19
    targetSdkVersion 27
    versionCode 1
    versionName '1.0'

    testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
  }

  sourceSets {
    main.java.srcDirs += 'src/main/kotlin'
    test.java.srcDirs += 'src/test/kotlin'
    androidTest.java.srcDirs += 'src/androidTest/kotlin'
  }

  buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }
}

dependencies {
  implementation 'com.android.support:appcompat-v7:27.1.0'

  implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlinVersion"

  testImplementation 'junit:junit:4.12'

  androidTestImplementation 'com.android.support.test:runner:1.0.1'
  androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}

Aproveitando que estamos modificando as configurações de build do nosso projeto, recomendo atualizarmos também a versão do Gradle que está sendo utilizada. Para isso, basta gerarmos o wrapper apontando para a versão mais recente (4.6 no momento em que escrevo este post). A não ser quando há imcompatibilidades entre o plugin do Android e o Gradle, sempre recomendo a utilização da versão mais recente do Gradle, já que ela costuma trazer melhorias importantes de performance (o que é sempre bem-vindo). Para atualizar o wrapper, basta executar o seguinte comando:

./gradlew wrapper --gradle-version 4.6 --distribution-type all

Para que nosso aplicativo já tenha uma Activity inicial, também adicionei uma MainActivity vazia e adicionei ao Android Manifest. Também aproveitei e exclui os testes que vem por padrão no template do Android Studio - assim que começarmos a entrar nas features do app, escreveremos os nossos :)

Seguindo o nosso Git Flow, criei um Pull Request para a branch develop, que, assim que passou no CI, foi mergeado :)

Por hoje é isso. Apesar deste post não mostrar nada muito novo, acho importante configurarmos o Kotlin por nós mesmos e saber o que muda no projeto. Afinal, os build scripts também são código, e mantê-los organizados faz parte da saúde do projeto. Aguardem que no próximo post teremos mais coisas interessantes.

Até lá!