深入理解groovy
静态分派 动态分派
MethodHandle与反射Method区别
Call Site分析
JVM invokedynamic调用指令
元编程:
维基百科 上将元编程描述成一种计算机程序可以将代码看待成数据的能力。
如果能够将代码看做数据,那么代码就可以像数据一样在运行时被修改、更新和替换(你学过编译原理就知道,在 CPU 眼里,程序本来就是数据。先把文本形式的代码变成 Token,再变成 AST,然后是 IR,最后是汇编代码和机器代码。);元编程赋予了编程语言更加强大的表达能力,通过编译期间的展开生成代码或者允许程序在运行时改变自身的行为。归根结底就是一种使用代码生成代码的思想,消灭重复的代码,极大地增强编程语言的表达能力。
CallSite
invokedynamic 是 Java 7 引入的一条新指令,用以支持动态语言的方法调用。具体来说,它将调用点(CallSite)抽象成一个 Java 类,并且将原本由 Java 虚拟机控制的方法调用以及方法链接暴露给了应用程序。在运行过程中,每一条 invokedynamic 指令将捆绑一个调用点,并且会调用该调用点所链接的方法句柄。
可以动态注入 属性 方法
class Sutdent {
String name
Integer age
def Hellow() {
return "hello"
}
def invokeMethod(String name, Object args) {
println "name:"+name + " args:"+args
}
}
Sutdent.metaClass.sex = "女"
Sutdent.metaClass.set123 = { a, b -> a + b }
def stdent = new Sutdent(name: "xiaoming", age: 12, sex: "nnn")
println(stdent.sex)
println("set123:"+stdent.set123(10,2))
生命周期
ext
apply from: this.file('commom.gradle')
gradle.properties
依赖冲突
传递依赖
外部命令
task('apkcopy') {
doLast {
def sourcePath = this.buildDir.path + '/outputs/apk'
def desActionPath = '/Users/ssy/Desktop/'
def command = "mv -f ${sourcePath} ${desActionPath}"
exec {
try {
executable 'bash'
args '-c', command
println 'the command is execute success'
} catch (GradleException e) {
println 'the command is execute failed'
}
}
}
}
Task执行顺序
task lib2() {
doLast { println 'lib2' }
}
task lib1(dependsOn: lib2) {
doLast {
println 'lib1'
}
}
task lib3 {
doLast { println 'lib3' }
}
task lib2() {
doLast { println 'lib2' }
}
task nlib1() {
dependsOn this.tasks.findAll {
task ->
return task.name.startsWith('lib')
}
doLast {
println 'nlib1'
}
}
task lib3 {
doLast { println 'lib3' }
}
task lib2() {
doLast { println 'lib2' }
}
task nlib1() {
// dependsOn this.tasks.findAll {
// task ->
// return task.name.startsWith('lib')
// }
dependsOn this.tasks.findByName("lib3")
doLast {
println 'nlib1'
}
}
实战
task autoVersionWrite {
File file = new File(this.getProjectDir().absolutePath + "/version.xml")
if (!file.exists()) {
file.createNewFile()
}
def releases = new XmlParser().parse(file)
def canWrite = true
def out = new StringWriter()
def xml = new groovy.xml.MarkupBuilder(out)
xml.releases {
releases.release.each {
release1 ->
if (Integer.parseInt(release1.versionCode.text()) == rootProject.ext.android.versionCode) {
canWrite = false
}
release {
versionCode(release1.versionCode.text())
versionName(release1.versionName.text())
versionInfo(release1.versionInfo.text())
}
}
if (canWrite) {
release {
versionCode(rootProject.ext.android.versionCode)
versionName(rootProject.ext.android.versionName)
versionInfo(rootProject.ext.android.versionInfo)
}
}
}
def xmlString = """<?xml version='1.0' encoding='UTF-8'?>
""";
file.write(xmlString + out.toString());
}
<?xml version='1.0' encoding='UTF-8'?>
<releases>
<release>
<versionCode>10</versionCode>
<versionInfo>app 的第一个版本</versionInfo>
<versionName>1.0</versionName>
</release>
<release>
<versionCode>12</versionCode>
<versionInfo>app 的第二个版本,上线了一些核心功能</versionInfo>
<versionName>1.2</versionName>
</release>
<release>
<versionCode>13</versionCode>
<versionInfo>app 的第三个版本,上线了一些核心功能</versionInfo>
<versionName>1.3</versionName>
</release>
<release>
<versionCode>20</versionCode>
<versionInfo>app 的第二十个版本,这是一个大版本更新</versionInfo>
<versionName>2.0</versionName>
</release>
</releases>
任务的输入输出
挂接自定义Task到构造过程中
https://www.imooc.com/article/68468
Settings
依赖-管理依赖的版本(传递(transitive)\排除(exclude)\强制(force)\动态版本(+))
https://blog.csdn.net/l419070777/article/details/79473990
SourceSet
sourceSets {
main {
res.srcDirs = ['src/main/res','src/main/res-ad','src/main/res-player']
// main.res.srcDirs += ['src/main/res-qa', 'src/main/res-wb']
}
}
Plugin 中引用包
@AutoService(VariantProcessor::class)
class ThreadVariantProcessor : VariantProcessor {
override fun process(variant: BaseVariant) {
if (variant !is LibraryVariant) {
var baseVariantData = (variant as ApplicationVariantImpl).variantData
var p = baseVariantData.scope.globalScope.project
p.dependencies.add(
"implementation", "com.ssy.ferry:ferry-android-instrument-thread:1.0.1}"
)
}
}
}