Android插件配置-Android Extension介紹

我們先來看一個簡單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對象配置

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章