IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android Gradle的神奇之处 ---- Project和Gradle插件 -> 正文阅读

[移动开发]Android Gradle的神奇之处 ---- Project和Gradle插件

之前Android Gradle的神奇之处 ---- Gradle构建和Task引入对Task任务做了简单的介绍,本节着重介绍自定义Task任务之间的联动

1 Task任务的输入输出

通常,Task任务的输入就是某个Task任务的输出,例如apk打包,就经过dex打包,apkbuilder压缩,apk签名等,每个流程的输出都是下一个流程的输出,在自定义Task任务中,@Input和@OutputFile代表当前的输入和输出

1.1 @Input @OutputFile

class MyTask extends DefaultTask{

    @Input
    def inputPath
    
    @OutputFile
    def outFile

    MyTask(){
        group 'custome'
        println 'MyTask 构造方法 配置阶段执行'
    }

    @TaskAction
    def Action(){

        println 'MyTask 执行了'
    }
}

如果在没有指定输入和输出的情况下,执行task任务会报错

Type 'MyTask' property 'inputPath' doesn't have a configured value.

使用@Optional注解,代表当前属性可选,可以选择不传数据,就不会报错

1.2 inputs.file outputs.files

如果不想使用1.1中的注解,还可以通过其他的方式,给当前的task设置输入和输出

inputs.files file('build.gradle')
outputs.files file('text.txt')

使用inputs.files和outputs.files可以给当前任务输入或者输出一个文件

如果想要获取输入的文件,因为当前只输入一个文件,可以使用singleFile获取文件内容

inputs.files.singleFile

这里进行了一个简单的读写操作,将输入文件的内容复制到了输出文件中

@TaskAction
def Action(){

    println 'MyTask 执行了'
    println inputs.files.singleFile

    def inFile = inputs.files.singleFile
    def outFile = outputs.files.singleFile
    //创建输出文件
    outFile.createNewFile()
    //通过text直接赋值即可
    outFile.text = inFile.text
}

2 系统内置任务

2.1 Zip

Zip是系统自带的一个zip任务,能够把目标文件夹的内容打成zip包发布
在这里插入图片描述

task zipTask(type: Zip){

    //build文件夹
    archiveName 'build.zip'
    destinationDir project.buildDir

    from project.buildDir
}

这里有几个参数需要明确一下
from:待压缩的文件所在的文件夹,project.buildDir为build文件夹,每个模块下都有自己的build文件夹
archiveName:压缩后的文件名
destinationDir:压缩后的文件存放位置

2.2 packageDebug

在app工程下,build/outputs下回生成对应的 debug apk 或者 release apk,如果想要获取build文件夹下的outputs文件夹,需要使用packageDebug任务,那么首先就要获取packageDebug任务;

tasks.getByName('packageDebug')
A problem occurred evaluating project ':app'.
> Task with name 'packageDebug' not found in project ':app'.

任务是在配置阶段生成的,如果直接拿是拿不到的,之前讲到过的钩子函数就可以帮助在任务创建之后,拿任务,这个时候肯定拿的到

project.afterEvaluate{
    //任务配置完成之后
    println tasks.getByName('packageDebug')
    task zipTask(type: Zip){

        //build文件夹
        archiveName 'build.zip'
        destinationDir project.buildDir

        from tasks.getByName('packageDebug').outputs.files
    }
}

在这里插入图片描述

3 Task的增量构建

当多次执行gradle脚本构建的时候,第一次所有的task任务都会执行,但是如果同样的task再执行一次,就不会再次执行action中的操作,而是默认使用上次构建的,像Task B UP-TO-DATE,就是没有执行

> Task :B UP-TO-DATE

> Task :A
A do First

> Task :finalizeTask UP-TO-DATE

> Task :C
C do First
C do doLast

这就是增量构建,增量构建的原理就是监控input的变化,只有input发送变化了,才重新执行task任务,否则gradle认为可以重用之前的执行结果

4 Project

每个moudle都对应了一个project对象,因通过project对象就可以对每个项目做配置

project(':app'){
	//这里是不支持 plugins{ } 需要apply
    apply plugin:'com.android.application'
    apply plugin:'kotlin-android'
    apply plugin:'kotlin-kapt'

    println("组件化")

//性能上的优化
    def config = rootProject.ext.androidId
    def dependency = rootProject.ext.dependency

    android {
        compileSdk config.compileSdk

        defaultConfig {
            applicationId "com.study.modulelization"
            minSdk config.minSdk
            targetSdk config.targetSdk
            versionCode config.versionCode
            versionName config.versionName

            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

            buildConfigField("Boolean", "isRelease", "${rootProject.isRelease}")

            kapt {
                arguments{
                    arg("moduleName","app")
                }
            }


        }

        buildTypes {

            debug {
                buildConfigField("String", "debugUrl", "\"${rootProject.url.DEBUG} \"")
            }

            release {
                buildConfigField("String", "releaseUrl", "\"${rootProject.url.RELEASE}\"")
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            }
        }
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }


        kotlinOptions {
            jvmTarget = '1.8'

        }
    }

    dependencies {

        implementation 'androidx.appcompat:appcompat:1.4.1'
        implementation 'com.google.android.material:material:1.5.0'
        implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
        implementation project(path: ':complier_api2')
        dependency.each { k, v -> implementation v }

        if (rootProject.isRelease) {
            //依赖包
            implementation project(path: ':register')
            implementation project(path: ':lay_router')
            kapt project(path: ':lay_compiler')
            implementation project(':complier_api2')
            implementation project(':commonlib')

        }

        testImplementation 'junit:junit:4.+'
        androidTestImplementation 'androidx.test.ext:junit:1.1.3'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
        implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.2.0'
        implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1'
        implementation 'androidx.lifecycle:lifecycle-livedata-core-ktx:2.4.1'
        implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
        implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2'
    }
}

这里通过project(‘模块名称’),在闭包中就可以对当前模块做配置,其实这样就代替了app模块中的build.gradle

通过subprojects则是可以获取到全部的子工程的project对象

4.1 ext属性扩展

ext属性扩展,其实就是对project对象做属性扩展

# ext.gradle

ext {
    prop1 = 'prop1'
}

在根 build.grdle中做了属性扩展,实际上就是对rootProject做了扩展,那么每个子模块都能拿到这个rootProject,相当于在build.grdle中声明了一个变量

# 根 build.gradle

project.ext.prop2 = 'prop2'

在子模块中,去获取这个变量,注意是使用rootProject

# register模块 --- build.gradle

println rootProject.prop1
println rootProject.prop2

输出
prop1
prop2

1~ 对于所有对象都可以属性扩展,通过ext{ }闭包或者直接赋值 ext.prop = …
2~ 由谁调用,就是给谁做扩展,例如project中调用,就是给project做扩展,一般情况下都是
3~ 在build.gradle中,默认就是给当前工程的project做扩展,在根build.gradle中就是给rootProject做扩展,所有的moudle都可以使用这个扩展属性

5 Gradle插件

gradle插件就是提供给gradle构建工具,在编译时的依赖项;主要的目的就是抽取公共的构建业务,达到复用的效果

像系统提供的一些任务,都是剥离出来可复用的,之前常见的Zip、Clean,都是插件中的任务;Gradle插件共分为2种,接下来讲解第一种

5.1 脚本插件

脚本插件是比较常见的一种插件,在之前就已经写过一些,比如抽离一个压缩zip的任务,可以提供给某个模块使用

# zip.gradle

project.afterEvaluate{
    task zipTask(type:Zip){

        archiveName 'zip01.zip'
        destinationDir "${project.buildDir}/custome"
        from tasks.getByName('packageDebug').outputs.files
    }
}
# app/build.gradle
apply from:'/****/zip.gradle'

通过apply的方式就完成了脚本的注入,可以执行task任务

5.2 二进制插件

二进制插件,就是将脚本打成jar包,实现jar包依赖

# 根 build.gradle
class MyPluginTask implements Plugin<Project>{

    @Override
    void apply(Project target) {

        println 'MyPluginTask apply'
    }
}

二进制插件实现了Plugin接口,重写apply方法,在apply方法中做业务打包,使用方式还是apply,只不过是使用plugin作为key

# 根 build.gradle
apply plugin: MyPluginTask

像这种方式是只能在一个模块中使用这个二进制插件,如果想要所有的项目共享,那么就需要将这个插件上传maven私服,那么在使用的时候,将这个插件拉取下来使用

5.2.1 buidSrc

创建一个buildSrc文件夹,注意!不能写错,然后重新rebuild一下工程
在这里插入图片描述
然后,需要创建一个src/main/java文件夹,如果使用Java编写就创建java文件夹,使用groovy编写就创建groovy文件夹

public class MyTargetPlugin implements Plugin<Project> {

    @Override
    public void apply(Project project) {

        System.out.println("这是自定义的二进制插件"+project.getClass());
    }
}

当创建这个二进制插件之后,就可以在任意一个moudle中使用

# register/build.gradle

apply plugin: MyTargetPlugin

我们可以看到,在buildSrc的libs文件夹下有一个jar包,这个jar包就可以上传到maven仓库
在这里插入图片描述

5.2.2 buildSrc简介

buildSrc是Android工程默认的一个插件工程,有且仅有一个,能够直接实现插件的封装

settingsEvaluated
projectsLoaded
> Task :buildSrc:compileJava UP-TO-DATE
> Task :buildSrc:compileGroovy NO-SOURCE
> Task :buildSrc:processResources
> Task :buildSrc:classes
> Task :buildSrc:jar
> Task :buildSrc:generateSourceRoots UP-TO-DATE
> Task :buildSrc:assemble
> Task :buildSrc:compileTestJava NO-SOURCE
> Task :buildSrc:compileTestGroovy NO-SOURCE
> Task :buildSrc:processTestResources NO-SOURCE
> Task :buildSrc:testClasses UP-TO-DATE
> Task :buildSrc:test SKIPPED
> Task :buildSrc:check SKIPPED
> Task :buildSrc:build

> Configure project :
资源回收
MyTask 构造方法 配置阶段执行

我们可以看到,在Gradle配置之前,就已经在编译阶段去编译这个buildSrc项目,然后配置到classpath下面,那么在gradle的配置阶段,就可以直接使用buildSrc中生成好的插件去做操作处理

使用buildSrc的好处在于,如果要修改插件内的内容,可以不用等发版,就直接在本地实现配置依赖,不用上传maven仓库,例如在插件中创建一个zip任务,不需要发版,在app模块中直接依赖即可

public class MyTargetPlugin implements Plugin<Project> {

    @Override
    public void apply(Project project) {

        System.out.println("这是自定义的二进制插件"+project.getClass());

        project.afterEvaluate(new Action<Project>() {
            @Override
            public void execute(Project project) {

                File buildDir = project.getBuildDir();
                Task packageDebug = project.getTasks().getByName("packageDebug");

                Map<String,Class<?>> map = new HashMap<>();
                map.put("type", Zip.class);
                //Java 创建task
                Zip zipTask = (Zip) project.task(map,"pluginTask");
                //设置输入输出
                zipTask.setArchiveName("zip02.zip");
                zipTask.setDestinationDir(new File(buildDir.getAbsolutePath()));
                zipTask.from(packageDebug.getOutputs().getFiles());

            }
        });
    }
}

通过Java也可以实现,在gradle中创建zip任务的流程,就是写起来比较繁琐
在这里插入图片描述

# app/build.gradle
apply plugin: MyTargetPlugin
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-03-15 22:41:49  更:2022-03-15 22:42:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 17:59:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码