🌱 Branch: 10-11/customizing-android-options
🔗 Repositório: github.com/rsicarelli/kotlin-gradle-android-platform
⬅️ Artigo Anterior: Parte 10: Customização dos módulos
➡️ Próximo Artigo: Parte 12: Otimizando tempo de compilação para bibliotecas Android
No artigo anterior, parametrizamos os argumentos de applyAndroidApp()
e appyAndroidLibary()
com modelos.
Agora, as funções androidApp()
e androidLibrary()
devem ser modificadas para aplicar as devidas decorações nos módulos.
Definindo os valores através de uma DSL
Dentro das nossas funções androidApp()
e androidLibrary()
poderiamos simplesmente aceitar um modelo:
fun Project.androidApp(androidAppOptions: AndroidAppOptions) = applyAndroidApp(androidAppOptions) fun Project.androidLibrary(androidLibraryOptions: AndroidLibraryOptions) = applyAndroidLibrary(androidLibraryOptions)
Essa é uma abordagem totalmente válida! Porém, na hora de consumir, precisamos ter um "boilerplate" de definir uma nova classe:
androidApp( androidAppOptions = AndroidAppOptions( applicationId = "com.rsicarelli.plataforma", .. ) )
Isso é bem verboso, além de fugir um pouco do estilo "convencional" de DSL que encontramos nos arquivos build.gradle.kts
.
Para solucionar esse problema, vamos introduzir uma DSL que cuide dessa customização de uma forma elegante e idiomática no Kotlin.
Note que, aqui iremos definir os valores padrões da nossa plataforma.
abstract class AndroidOptionsBuilder { var namespace: String = "com.rsicarelli.kplatform" var compileSdk: Int = 34 var minSdk: Int = 24 var useVectorDrawables: Boolean = true var javaVersion: JavaVersion = JavaVersion.VERSION_17 var composeOptions: ComposeOptions = ComposeOptions() var packagingOptions: PackagingOptions = PackagingOptions() var buildTypes: List<AndroidBuildType> = listOf(ReleaseBuildType, DebugBuildType) abstract fun build(): AndroidOptions } class AndroidAppOptionsBuilder : AndroidOptionsBuilder() { var applicationId: String = "com.rsicarelli.kplatform" var targetSdk: Int = 34 var versionCode: Int = 1 var versionName: String = "1.0" private var proguardOptionsBuilder = ProguardOptionsBuilder("proguard-rules.pro") fun proguardOptions(init: ProguardOptionsBuilder.() -> Unit) { proguardOptionsBuilder.apply(init) } override fun build(): AndroidAppOptions = AndroidAppOptions( applicationId = applicationId, targetSdk = targetSdk, versionCode = versionCode, versionName = versionName, proguardOptions = proguardOptionsBuilder.build(), namespace = namespace, compileSdk = compileSdk, minSdk = minSdk, useVectorDrawables = useVectorDrawables, javaVersion = javaVersion, composeOptions = composeOptions, packagingOptions = packagingOptions, buildTypes = buildTypes ) } class AndroidLibraryOptionsBuilder : AndroidOptionsBuilder() { private var proguardOptionsBuilder = ProguardOptionsBuilder("consumer-proguard-rules.pro") fun proguardOptions(init: ProguardOptionsBuilder.() -> Unit) { proguardOptionsBuilder.apply(init) } override fun build(): AndroidLibraryOptions = AndroidLibraryOptions( proguardOptions = proguardOptionsBuilder.build(), namespace = namespace, compileSdk = compileSdk, minSdk = minSdk, useVectorDrawables = useVectorDrawables, javaVersion = javaVersion, composeOptions = composeOptions, packagingOptions = packagingOptions, buildTypes = buildTypes ) } class ProguardOptionsBuilder(defaultFileName: String) { var fileName: String = defaultFileName var applyWithOptimizedVersion: Boolean = true fun build(): ProguardOptions = ProguardOptions( fileName = fileName, applyWithOptimizedVersion = applyWithOptimizedVersion ) }
Expondo nossos builder
nas funções androidApp()
e androidLibrary()
Note que passamos uma lambda vazia como parametro, possibilitando o módulo simplesmente invocar com as opções pre-definidas.
fun Project.androidApp(builderAction: AndroidAppOptionsBuilder.() -> Unit = { }) = applyAndroidApp(AndroidAppOptionsBuilder().apply(builderAction).build()) fun Project.androidLibrary(builderAction: AndroidLibraryOptionsBuilder.() -> Unit = { }) = applyAndroidLibrary(AndroidLibraryOptionsBuilder().apply(builderAction).build())
Uso
Uso é super flúido, olha só como podemos customizar versionCode
e versionName
no app/build.gradle.kts
:
androidApp { // this é o AndroidAppOptionsBuilder versionCode = 1 versionName = "1.0.0" proguardOptions { // this é ProguardOptionsBuilder applyWithOptimizedVersion = true } }
Sucesso!
Agora, nossa configuração está elegante com uma DSL expressiva e intuitiva, permitindo diversas customizações adaptáveis para diferentes cenários.
Essa abordagem nos permite estabelecer comportamentos padrão para os módulos, mas também oferece uma DSL robusta para que o time consiga adicionar novas configurações conforme necessário.
No próximo artigo, vamos adicionar uma decoração importantíssima para otimizar o tempo de compilação dos nossos módulos.
Top comments (0)