Android插件配置-Android Extension介绍

司马飞鸿
2023-12-01

我们先来看一个简单app的build.grdle的定义

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    buildToolsVersion "28.0.3"
    defaultConfig {
        applicationId "com.harish.test.sample"
        minSdkVersion 21
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
    }

    signingConfigs {
        release {
            storeFile file('keys/test.jks')
            storePassword '123'
            keyAlias 'mainkey'
            keyPassword '123'
            v2SigningEnabled true
        }
    }

    buildTypes {
        release {
            signingConfig signingConfigs.release

            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        debug {
            minifyEnabled false
            debuggable true
            jniDebuggable true
        }
    }
}

dependencies {
    api fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:28.0.0'
}

我们可以认为build.gradle文件的内容,是以闭包的形式被执行的,这个闭包的delegate是project,先看project的类继承信息

@HasInternalProtocol
public interface Project extends Comparable<Project>, ExtensionAware, PluginAware {
    ***
}

从继承信息可以看出,project支持extension和plugin

重新回到build.gradle,dependencies是调用project的函数,apply则是应用插件,android则是一个extension

接着重点讲讲extension,project是ExtensionAware的,就说明其可以创建extension

project.extensions.create('android', AppExtension)

创建成功后,可以有两个方式访问extension对象

//通过project属性
project.android.*** = 
//通过namespace method
project.android{
    
}

build.gradle明显使用的是第二种,android extension里头的配置,明显都是函数调用,有些是直接配置值的,比如

    compileSdkVersion 28
    buildToolsVersion '28.0.3'

有些传得则是闭包

    defaultConfig {
        versionName "1.1"
        versionCode 104
        targetSdkVersion 28
        applicationId "com.harishhu.replugin.sample.demo1"
        minSdkVersion 15
        multiDexEnabled false
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

如果要传入闭包,则函数定义的最后一个参数,必须是Closure或者Action,比如:

//配置
repositories {
    flatDir {
        dirs 'libs'
    }
}
//对应函数定义
/**
* <p>Configures the repositories for this project.
*
* <p>This method executes the given closure against the {@link RepositoryHandler} for this project. The {@link
* RepositoryHandler} is passed to the closure as the closure's delegate.
*
* @param configureClosure the closure to use to configure the repositories.
*/
void repositories(Closure configureClosure);
//配置
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
//对应函数定义
public void buildTypes(Action<? super NamedDomainObjectContainer<BuildType>> action) ;

那Closure和Action有什么区别?个人觉得最大的区别是,光从函数的定义,Closure是无法知晓闭包的运行作用域的,必须在函数注释里给予描述,比如repositories就说明了,闭包的delegate是RepositoryHandler

但是Action则不一样,先看Action的定义

public interface Action<T> {
    /**
     * Performs this action against the given object.
     *
     * @param t The object to perform the action on.
     */
    void execute(T t);
}

这是个模版接口,T则明确指明了闭包运行时的附属对象类型,继续拿build types举例

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        
        debug{
            minifyEnabled false
        }
    }

接着看buildTypes函数实现

public void buildTypes(Action<? super NamedDomainObjectContainer<BuildType>> action) {
    checkWritability();
    action.execute(buildTypes);
}

buildTypes即闭包执行的附属对象,execute执行完后,相当于在buildTypes添加了属性名分别为release和debug两个BuildType对象配置

 类似资料: