}
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 pluginPlugin 之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.Pluginclass 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移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
尾声
最后,我再重复一次,如果你想成为一个优秀的 Android 开发人员,请集中精力,对基础和重要的事情做深度研究。
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。
最后想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。
当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。
进阶学习视频
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。
进阶学习视频
[外链图片转存中…(img-kgg8ednL-1712767053005)]
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
[外链图片转存中…(img-2lNvfdD3-1712767053005)]
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-AVGqOS6x-1712767053005)]-