Ricardo C.
12/27/2023, 10:06 AMafterEvaluate
or understand Gradle lifecycle to configure things at specific times, otherwise the module wouldn’t have set up things yet and it would just hit the convention values.
Instead I came up with this:
class AndroidLibraryConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
with(pluginManager) {
apply("com.android.library")
apply("org.jetbrains.kotlin.android")
}
...
extensions.create(AndroidLibraryExtension::class, "gst", AndroidLibraryExtensionImpl::class, target)
}
}
}
interface AndroidLibraryExtension {
fun compose()
}
internal abstract class AndroidLibraryExtensionImpl(
private val project: Project,
) : AndroidLibraryExtension {
override fun compose() = with(project) {
extensions.configure<LibraryExtension> {
configureCompose(this)
}
}
}
Is this a common practice? Does it have any drawback I’m not thinking of? I couldn’t really find much about this topic.
Thank you!Vampire
12/27/2023, 10:34 AMafterEvaluate
you should avoid as hell. Using it is most often just symptom treatment. It is like using SwingUtilities.runLater
or Platform.runLater
to "fix" a GUI Bug. It just shifts the problem to a later point in time where it is harder to reproduce, harder to debug, and harder to fix. The main effect of afterEvaluate
is to introduce timing problems, ordering problems, and race conditions. If you got example read the configuration in afterEvaluate
, but the user also uses afterEvaluate
after you and therein does the configuration, you again miss it. There are some edge cases where it might unavoidable to use it, but in most cases it is better to use some alternative. Having a function in the extension that does some configuration is such an alternative. You don't necessarily need to split the extension into interface and implementation for that, but you can.Ricardo C.
12/27/2023, 10:47 AMYou don’t necessarily need to split the extension into interface and implementation for that, but you can.I couldn’t find any method that would let me pass constructor params and a single type, so I guess I would just pass the same type in both?
extensions.create(AndroidLibraryExtension::class, "gst", AndroidLibraryExtension::class, target)
Vampire
12/27/2023, 11:00 AM@Inject
.
But actually, you can just leave out the explicit constructor argument. For Project
on an extension constructor it just automagically works: https://github.com/gradle/gradle/issues/27427Ricardo C.
12/27/2023, 11:41 AM