🌱 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)