DSL

作者: Drew_MyINTYRE | 来源:发表于2020-12-06 12:45 被阅读0次

NamedDomainObjectContainer

顾名思义就是命名领域对象容器,它的主要功能有:

  • 通过DSL创建指定type的对象实例

  • 指定的type必须有一个public构造函数,且必须带有一个String name的参数

  • 它是一个实现了SortedSet接口的容器,所以所有领域对象的name属性都必须是唯一的,在容器内部会用name属性来排序

Gradle 中有很多容器类的迭代遍历方法有 each(Closure action)、all(Closure action),但是一般我们都会用 all(...) 来进行容器的迭代。all(...) 迭代方法的特别之处是,不管是容器内已存在的元素,还是后续任何时刻加进去的元素,都会进行遍历。

buildTypes {}

defaultConfig {}

productFlavors{}

//上面的扩展函数就是这么来的
    private final DefaultConfig defaultConfig;
    private final NamedDomainObjectContainer<ProductFlavor> productFlavors;
    private final NamedDomainObjectContainer<BuildType> buildTypes;
    private final NamedDomainObjectContainer<SigningConfig> signingConfigs;
    public void defaultConfig(Action<DefaultConfig> action) {
        this.checkWritability();
        action.execute(this.defaultConfig);
    }
    
     public void buildTypes(Action<? super NamedDomainObjectContainer<BuildType>> action) {
        this.checkWritability();
        action.execute(this.buildTypes);
    }
    public void productFlavors(Action<? super NamedDomainObjectContainer<ProductFlavor>> action) {
        this.checkWritability();
        action.execute(this.productFlavors);
    }
    public void signingConfigs(Action<? super NamedDomainObjectContainer<SigningConfig>> action) {
        this.checkWritability();
        action.execute(this.signingConfigs);
    }

// android{}这么来的
//AppPlugin 就是插件 com.android.application 的实现类,
//LibraryPlugin 则是插件 com.android.library 的实现类,
//接着再看看 AppPlugin 里是怎样创建 Extension 的:
public class AppPlugin extends BasePlugin implements Plugin<Project> {
    @Inject
    public AppPlugin(Instantiator instantiator, ToolingModelBuilderRegistry registry) {
        super(instantiator, registry);
    }
    protected BaseExtension createExtension(Project project, ProjectOptions projectOptions, Instantiator instantiator, AndroidBuilder androidBuilder, SdkHandler sdkHandler, NamedDomainObjectContainer<BuildType> buildTypeContainer, NamedDomainObjectContainer<ProductFlavor> productFlavorContainer, NamedDomainObjectContainer<SigningConfig> signingConfigContainer, NamedDomainObjectContainer<BaseVariantOutput> buildOutputs, ExtraModelInfo extraModelInfo) {
        return (BaseExtension)project.getExtensions().create("android", AppExtension.class, new Object[]{project, projectOptions, instantiator, androidBuilder, sdkHandler, buildTypeContainer, productFlavorContainer, signingConfigContainer, buildOutputs, extraModelInfo});
    }
    public void apply(Project project) {
        super.apply(project);
    }
    //省略...
}

def getInfo() {
        //或者 直接 project.android
    BaseExtension extension = project.extensions.getByName("android")
    def android = project.extensions.getByType(AppExtension)
    project.android
    
    println "buildToolsVersion:${extension.buildToolsVersion}"
    println "compileSdkVersion:${extension.getCompileSdkVersion()}"
    println "applicationId:${extension.defaultConfig.applicationId}"
    println "minSdkVersion:${extension.defaultConfig.minSdkVersion}"
    println "targetSdkVersion:${extension.defaultConfig.targetSdkVersion}"
    println "versionCode:${extension.defaultConfig.versionCode}"
    println "versionName:${extension.defaultConfig.versionName}"
}

Instantiator

Instantiator 用于实例化对象, 使用Instantiator而不直接使用new,是因为使用Instantiator实例化对象时,会添加DSL特性

ExtensionContainer

它的作用就是通过实现自定义的 Extension,可以在 Gradle 脚本中增加类似 android 这样命名空间的配置,Gradle 可以识别这种配置,并读取里面的配置内容,一般我们通过ExtensionContainer来创建并管理Extension

/先定义一个普通的java类,包含2个属性
class Foo {
    int age
    String username
    String toString() {
        return "name = ${username}, age = ${age}"
    }
}
//创建一个名为 foo 的Extension
getExtensions().create("foo", Foo)
//配置Extension
foo {
    age = 30
    username = "hjy"
}
task testExt.doLast {
    //能直接通过 project 获取到自定义的 Extension
    println project.foo
}

相关文章

网友评论

      本文标题:DSL

      本文链接:https://www.haomeiwen.com/subject/zrknwktx.html