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