Android Gradle 学习笔记整理,2024年最新滴滴面试coding

}

allprojects {
}
println “project.root end”

//app build.gradle
println “project.app start”
project.afterEvaluate {
println “project.app.afterEvaluate print”
}
project.beforeEvaluate {
println “project.app.beforeEvaluate print”
}
println “project.app end”

如果是mac/linux,执行./gradlew 得到如下结果:

settings.gradle start
settings.gradle end

Configure project :
project.root start
project.root end

Configure project :app
project.app start
project.app end
project.app.afterEvaluate print

Groovy 语法

下面讲一些关于groovy的语法,可以打开Android Studio Tools-> Groovy Console练习Groovy 语法 ,如下

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可选的类型定义,可以省略语句结束符分号(;)

int vs = 1
def version = ‘version1’

println(vs)
println(version)

括号也是可选的

println vs
println version

字符串定义

def s1 = ‘aaa’
def s2 = “version is ${version}”
def s3 = ‘’’ str
is
many
‘’’
println s1
println s2
println s3

集合

def list = [‘ant’,‘maven’]
list << “gradle”
list.add(‘test’)
println list.size()
println list.toString()
//map
def years = [‘key1’:1000,“key2”:2000]
println years.key1
println years.getClass()

输出结果

[ant, maven, gradle, test]
1000
class java.util.LinkedHashMap

闭包

groovy语法中支持闭包语法,闭包简单的说就是代码块,如下:

def v = {
v -> println v
}
static def testMethod(Closure closure){
closure(‘闭包 test’)
}
testMethod v

其中定义的v就为闭包,testMethod 为一个方法,传入参数为闭包,然后调用闭包.

解释 apply plugin: 'xxxx’和 dependencies{}

准备工作,看gradle的源码

我们先把子项目的build.gradle改为如下形式

apply plugin: ‘java-library’
repositories {
mavenLocal()
}
dependencies {
compile gradleApi()
}

这样,我们就可以直接看gradle的源码了,在External Libraries里如下

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

解释

进入build.gradle 点击apply 会进入到gradle的源码,可以看到

//PluginAware
/**

  • Applies a plugin or script, using the given options provided as a map. Does nothing if the plugin has already been applied.
  • The given map is applied as a series of method calls to a newly created {@link ObjectConfigurationAction}.
  • That is, each key in the map is expected to be the name of a method {@link ObjectConfigurationAction} and the value to be compatible arguments to that method.
  • The following options are available:

    • {@code from}: A script to apply. Accepts any path supported by {@link org.gradle.api.Project#uri(Object)}.
  • {@code plugin}: The id or implementation class of the plugin to apply.
  • {@code to}: The target delegate object or objects. The default is this plugin aware object. Use this to configure objects other than this object.
  • @param options the options to use to configure and {@link ObjectConfigurationAction} before “executing” it
    */
    void apply(Map<String, ?> options);
  • 用Groovy 语法很清楚的解释,apply其实就是一个方法,后面传递的就是一个map,其中plugin为key.

    那么dependencies{}也是一样

    //Project
    /**

    • Configures the dependencies for this project.

    • This method executes the given closure against the {@link DependencyHandler} for this project. The {@link

    • DependencyHandler} is passed to the closure as the closure’s delegate.
    • Examples:

    • See docs for {@link DependencyHandler}
    • @param configureClosure the closure to use to configure the dependencies.
      */
      void dependencies(Closure configureClosure);

    dependencies是一个方法 后面传递的是一个闭包的参数.

    问题:思考那么android {}也是一样的实现吗? 后面讲解

    Gradle Project/Task

    在前面章节中提到gralde初始化配置,是先解析并执行setting.gradle,然后在解析执行build.gradle,那么其实这些build.gradle 就是Project,外层的build.gradle是根Project,内层的为子project,根project只能有一个,子project可以有多个.

    我们知道了最基础的gradle配置,那么怎么来使用Gradle里面的一些东西来为我们服务呢?

    Plugin

    前面提到apply plugin:‘xxxx’,这些plugin都是按照gradle规范来实现的,有java的有Android的,那么我们来实现一个自己的plugin.

    把build.gradle 改为如下代码

    //app build.gradle
    class LibPlugin implements Plugin{
    @Override
    void apply(Project target) {
    println ‘this is lib plugin’
    }
    }
    apply plugin:LibPlugin

    运行./gradlew 结果如下

    Configure project :app
    this is lib plugin

    Plugin 之Extension

    我们在自定义的Plugin中要获取Project的配置,可以通过Project去获取一些基本配置信息,那我们要自定义的一些属性怎么去配置获取呢,这时就需要创建Extension了,把上述代码改为如下形式。

    //app build.gradle
    class LibExtension{
    String version
    String message
    }
    class LibPlugin implements Plugin{
    @Override
    void apply(Project target) {
    println ‘this is lib plugin’
    //创建 Extension
    target.extensions.create(‘libConfig’,LibExtension)
    //创建一个task
    target.tasks.create(‘libTask’,{
    doLast{
    LibExtension config = project.libConfig
    println config.version
    println config.message
    }
    })
    }
    }
    apply plugin:LibPlugin
    //配置
    libConfig {
    version = ‘1.0’
    message = ‘lib message’
    }

    配置完成后,执行./gradlew libTask 得到如下结果

    Configure project :app
    this is lib plugin
    Task :lib:libTask
    1.0
    lib message

    看完上述代码,我们就知道android {} 其实他就是一个Extension, 他是由plugin ‘com.android.application’或者’com.android.library’ 创建。

    Task

    上述代码中,创建了一个名字为libTask的task,gradle中创建task的方式由很多中, 具体的创建接口在TaskContainer类中

    //TaskContainer
    Task create(Map<String, ?> options) throws InvalidUserDataException;
    Task create(Map<String, ?> options, Closure configureClosure) throws InvalidUserDataException;
    Task create(String name, Closure configureClosure) throws InvalidUserDataException;
    Task create(String name) throws InvalidUserDataException;
    T create(String name, Class type) throws InvalidUserDataException;
    T create(String name, Class type, Action<? super T> configuration) throws InvalidUserDataException;

    Project不可以执行跑起来,那么我们就要定义一些task来完成我们的编译,运行,打包等。com.android.application插件 为我们定义了打包task如assemble,我们刚才定义的插件为我们添加了一个libTask用于输出。

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    Task API

    我们看到创建的task里面可以直接调用doLast API,那是因为Task类中有doLast API,可以查看对应的代码看到对应的API

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    Gradle的一些Task

    gradle 为我们定义了一些常见的task,如clean,copy等,这些task可以直接使用name创建,如下:

    task clean(type: Delete) {
    delete rootProject.buildDir
    }

    依赖task

    我们知道Android打包时,会使用assemble相关的task,但是仅仅他是不能直接打包的,他会依赖其他的一些task. 那么怎么创建一个依赖的Task呢?代码如下

    task A{
    println “A task”
    }
    task B({
    println ‘B task’
    },dependsOn: A)

    执行./graldew B 输出

    A task
    B task

    自定义一个重命名APP名字的插件

    通过上述的一些入门讲解,大概知道了gradle是怎么构建的,那现在来自定义一个安卓打包过程中,重命名APP名字的一个插件。

    上述在build.gradle直接编写Plugin是OK的,那么为了复用性更高一些,那我们怎么把这个抽出去呢?

    如下

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    其中build.gradle为

    apply plugin: ‘groovy’
    apply plugin: ‘maven’
    repositories {
    mavenLocal()
    jcenter()
    }

    dependencies {
    compile gradleApi()
    }

    def versionName = “0.0.1”
    group “com.ding.demo”
    version versionName
    uploadArchives{ //当前项目可以发布到本地文件夹中
    repositories {
    mavenDeployer {
    repository(url: uri(‘…/repo’)) //定义本地maven仓库的地址
    }
    }
    }

    apkname.properties为

    implementation-class=com.ding.demo.ApkChangeNamePlugin

    ApkChangeNamePlugin

    package com.ding.demo

    import org.gradle.api.Project
    import org.gradle.api.Plugin

    class ApkChangeNamePlugin implements Plugin{

    static class ChangeAppNameConfig{
    String prefixName
    String notConfig
    }

    static def buildTime() {
    return new Date().format(“yyyy_MM_dd_HH_mm_ss”, TimeZone.getTimeZone(“GMT+8”))
    }

    @Override
    void apply(Project project) {
    if(!project.android){
    throw new IllegalStateException(‘Must apply ‘com.android.application’ or ‘com.android.library’ first!’);
    }
    project.getExtensions().create(“nameConfig”,ChangeAppNameConfig)
    ChangeAppNameConfig config
    project.afterEvaluate {
    config = project.nameConfig
    }
    project.android.applicationVariants.all{
    variant ->
    variant.outputs.all {
    output ->
    if (output.outputFile != null && output.outputFile.name.endsWith(‘.apk’)
    && !output.outputFile.name.contains(config.notConfig)) {
    def appName = config.prefixName
    def time = buildTime()
    String name = output.baseName
    name = name.replaceAll(“-”, “_”)
    outputFileName = “ a p p N a m e − {appName}- appName{variant.versionCode}- n a m e − {name}- name{time}.apk”
    }
    }
    }
    }
    }

    定义完成后,执行./gradlew uploadArchives 会在本目录生成对应对应的插件

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    应用插件 在根build.gralde 配置

    buildscript {
    repositories {
    maven {url uri(‘./repo/’)}
    google()
    jcenter()
    }
    dependencies {
    classpath ‘com.android.tools.build:gradle:3.4.1’
    classpath ‘com.ding.demo:apkname:0.0.1’
    }
    }

    在app.gralde 设置

    apply plugin: ‘apkname’
    nameConfig{
    prefixName = ‘demo’
    notConfig = ‘debug’
    }

    Gradle doc 官网

    Gradle的基础API差不多就介绍完了。

    官网地址:docs.gradle.org/current/use…
    可以去查看对应的API,也可以直接通过源码的方式查看

    但是笔记还没完,学习了Gradle的基础,我们要让其为我们服务。下面介绍几个实际应用.

    APT 技术

    www.jianshu.com/p/94aee6b02…
    blog.csdn.net/kaifa1321/a…

    APT 全称Annotation Processing Tool,编译期解析注解,生成代码的一种技术。常用一些IOC框架的实现原理都是它,著名的ButterKnife,Dagger2就是用此技术实现的,SpringBoot中一些注入也是使用他进行注入的.

    在介绍APT之前,先介绍一下SPI (Service Provider Interface)它通过在ClassPath路径下的META-INF/**文件夹查找文件,自动加载文件里所定义的类。 上面自定义的ApkNamePlugin 就是使用这种机制实现的,如下.

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    SPI 技术也有人用在了组件化的过程中进行解耦合。

    要实现一个APT也是需要这种技术实现,但是谷歌已经把这个使用APT技术重新定义了一个,定义了一个auto-service,可以简化实现,下面就实现一个简单Utils的文档生成工具。

    自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

    深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

    因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
    img
    img
    img
    img
    img
    img
    img

    既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

    由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

    如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
    img

    尾声

    最后,我再重复一次,如果你想成为一个优秀的 Android 开发人员,请集中精力,对基础和重要的事情做深度研究。

    对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

    最后想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

    当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

    进阶学习视频

    附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

    一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
    img
    构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

    当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

    进阶学习视频

    [外链图片转存中…(img-kgg8ednL-1712767053005)]

    附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

    [外链图片转存中…(img-2lNvfdD3-1712767053005)]

    一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
    [外链图片转存中…(img-AVGqOS6x-1712767053005)]

  • 25
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值