preface

To be a good Android developer, you need a complete set ofThe knowledge systemHere, let us grow together into what we think ~.

Groovy’s importance as the language at the heart of Gradle’s powerful building tool is self-evident, but Groovy itself is so complex that IT would take more than a few dozen swastikas to fully grasp it. Fortunately, the knowledge of Groovy in the Gradle world is very basic, so the purpose of this article is to lay a foundation for further exploration of Gradle.

First acquaintance with DSL

Domain Specific Languages (DSLS), such as Matliba, UML, HTML, XML, and so on. Groovy is a branch of DSL.

The characteristics of

  • 1) Solve domain specific problems.
  • 2) It goes to two extremes with system programming language. System programming language hopes to solve all problems. For example, Java language hopes to do Android development and server development, and it has the feature of horizontal expansion. DSLS have the ability to solve domain-specific problems in vertical depth.

In general, the core idea of DSLS is to solve domain-specific problems by focusing on specialization rather than completeness.

First acquaintance with Groovy

1. Groovy features

Groovy has the following three characteristics:

  • Groovy is an agile development language based on the JVM.
  • 2) Groovy combines many powerful features of Python, Ruby, and Smalltalk scripting languages.
  • 3) Groovy can integrate perfectly with Java and use all Java libraries.

So why make Grvooy when other scripting languages already exist?

Because Groovy is very cheap to get started with compared to other programming languages, and because its syntax is an extension of Java, we can learn Groovy the same way we learn Java.

2. Features of the Groovy language itself

Its characteristics are mainly as follows:

  • 1) Syntactically support dynamic type, closure and other new language features. Also, closures for the Groovy language are more powerful than closures for all other language types.
  • 2) It seamlessly integrates all existing Java libraries because it is based on the JVM.
  • 3) It supports both object-oriented programming (Java-based extensions) and procedural programming (a combination of many scripting languages).

Note that when we use Groovy for Gradle scripting, we use procedural programming.

3. Groovy’s advantages

Groovy has four advantages:

  • 1) It is a more agile programming language: besides a lot of syntactic sugar in building syntactically, much of the code that needs to be written in the Java layer can be omitted in Groovy. As a result, we can do more with less code.
  • 2) Simple to get started, but very powerful.
  • 3) It can be used as both a programming language and a scripting language
  • 4) Groovy will be very easy for those familiar with Java.

4. Groovy package structure

Groovy official website

Once you’ve downloaded the Groovy files from the official website, you can see the Groovy directory structure, where you’ll need to focus on the bin and doc folders.

Bin folder

The next three important executable files we need to know about in the bin folder are as follows:

  • Groovy commands are similar to Java commands in Java and are used to execute Groovy Class bytecode files.
  • 2) The Groovyc command is similar to the Javac command in Java and is used to compile Groovy source files into Groovy bytecode files.
  • 3) The Groovysh command explains the execution of Groovy script files.

Doc folder

Under the doc folder there is an HTML file, where the API and documentation we need to focus on are as follows:

  • API:A set of apis and documentation are provided for us in Groovy.
  • Documentation:Here are some tutorials from Groovy.

5. Keywords in Groovy

Here are all the keywords in Groovy, especially when naming them, as follows:

as,assert,break,case,catch,class,const,continue,def,default,do,else,enum,extends,false,finally,for,goto,if,implements,import,in,instanceof,interface,new,null,package,return,super,switch,this,throw,throws,trait,true,try,while
Copy the code

6. Groovy && Java difference learning

Getter/setter

For each field, Groovy automatically creates corresponding getters and setters that can be called directly from the outside, And when you get a value using Object.fielda or assign a value using Object.fielda = value, the object.getFielda () and Object.setfielda (value) methods are actually automatically called instead.

We can use the.@ direct domain access operator if we don’t want to call this particular getter method.

2) In addition to no bonus points per line of code, Groovy also allows function calls without parentheses.

Note that we can use this function without parentheses if it is a common Groovy or Gradle API function, such as println. Otherwise, keep the parentheses. Otherwise, Groovy might confuse properties with function calls.

3) Groovy statements can be terminated without semicolons.

4) When a function is defined, the type of the parameter may not be specified.

5) The return value of Groovy functions can also be untyped, and functions that do not return types are internally treated as returning Object types.

If the function does not return a value using the return keyword, the default value is null, but the def keyword must be used.

In Groovy, you can omit.class for all Class types.

In Groovy, == equals to Java. If you want to compare two objects to be the same, use.is().

Groovy non-operators are as follows:

assert (!"android") = =false                      
Copy the code

Groovy supports the ** operator as follows:

assert  2六四屠杀3= =8
Copy the code

11) Judge whether it is true more succinctly:

    if (android) {}
Copy the code

12) Ternary expressions can be more concise:

// omit name
defresult = name ? :"Unknown"
Copy the code

13) concise non-null judgment

println order? .customer? .addressCopy the code

Use assert to set assertions. When the assert condition is false, the program will throw an exception.

15) We can use the Number class to replace float, double, and so on.

16) The switch method can support more parameter types simultaneously.

Note that SWCTCH can match any element in the list, as shown in the sample code below:

/ / output is ok
def num = 5.21
switch (num) {
   case [5.21.4."list"] :return "ok"
       break
   default:
       break
}
Copy the code

Groovy basic syntax

Groovy’s basic syntax can be broken down into four main parts:

  • 1) Groovy’s core basic syntax.
  • 2) Groovy closures.
  • 3) Groovy data structures.
  • 4) Groovy is object-oriented

1. Groovy core basic syntax

Variables in Groovy

Variable types

In Groovy, as in Java, there are two types:

  • 1) Basic types.
  • 2) Object type.

Groovy is a dynamic language in which everything is an object, just like Python and Kotlin: all primitive types are object types. To verify this Case, we can create a new Groovy file, create a variable of type int and print it, which will result in ‘class java.lang.Integer’, so we can verify that we are right. In fact, Groovy’s compiler wraps all primitive types as object types.

Variable definitions

Groovy variables are defined quite differently from the way they are defined in Java. For Groovy, there are two ways to define variables, as follows:

  • 1) Strongly typed: Groovy, like Java, allows you to define strongly typed variables, such as x, as an int. This is called strongly typed.
  • 2) Weak type definition: we do not need to specify the type in advance like strong type. Instead, we use the def keyword to define any of our variables, because the compiler automatically assigns values based on the type of values.

So, in what scenarios should these two approaches be used?

If the variable is intended for the current class or file, and not for another class or application module, then def is recommended, because weak typing is sufficient in this scenario.

However, if you want to use a class or variable for another module, it is recommended not to use def. Instead, you should use Java’s strong type definition method, because with strong type definition, it cannot be dynamically converted to another type. It can guarantee that the value passed in from the outside is correct. If your variable is to be used by the outside world, and you use def to define it, what is the right thing for the outside world to pass you? This can confuse the caller.

If we change x1 to String in the following code, x1 will be inferred to String by the compiler, and we can guess that the variable defined using the def keyword is Obejct.

Strings in Groovy

Strings in Groovy are quite different from strings in Java, so we’ll focus on that here.

In addition to inherits Java’s traditional String usage, Groovy has added a new GString type, which can be used in at least seven or eight ways, but is commonly defined in three ways. In addition, a new set of operators have been added to GString to make it easier to manipulate String variables. Finally, there is a new set of useful apis in GString that we need to focus on.

There are three commonly used string definitions in Groovy

There are three common ways to define strings in Groovy, as follows:

  • 1) string defined by single quotation marks
  • 2) string defined by double quotes “”
  • 3), a string defined by triple quotes ‘”” “”

First, it’s important to note that ‘either single, double, or triple quotes are of type java.lang.string’.

So what’s the difference between a single quote and a triple quote?

In fact, it is not true. We need to add ” when we write a single quoted string with an escape character, and forcing a single quoted string into multiple lines becomes a string concatenation of ‘+’ signs when the string needs to be multi-line formatted.

What’s the difference between a variable defined by a double quote and a single or triple quote?

Unlike single and triple quotes, double quotes define an extensible variable. Let’s take a look at the two ways in which double quotes are used, as shown below:

In the figure above, the first name String is a regular String, while the sayHello String is an extensible String because it refers to the name variable as ‘${name}’. And the output can be seen from its final type, extensible type is’ org. Codehaus. Groovy. Runtime. GStringImpl ‘type.

Note that extensible strings can be extended into arbitrary expressions, such as mathematical operations, such as the sum variable in the figure above.

With Groovy’s extensible strings, we can avoid concatenation of strings in Java and improve the runtime performance of Java programs.

So, since there are two types of strings, String and GString, do they need to be strong-cast before they are assigned to each other?

No, the compiler automatically converts between String and GString, so we don’t have to worry too much about the differences when we write.

2. Groovy Closures

The essence of a closure is a code block. The core content of a closure can be summarized as follows:

  • 1) Closure concept
    • define
    • Closure calls
  • 2) Closure parameters
    • Common parameters
    • Implicit parameter
  • 3) Closure return value
    • There is always a return value

Closure calls

clouser.call()
clouser() 
def xxx = { paramters -> code } 
defXXX = {pure code}Copy the code

From a C/C++ language perspective, closures are similar to function Pointers. Closures can be called with the.call method, or their constructor can be called directly, as follows:

Closure object. call(parameter) Closure object (parameter)Copy the code

If the closure does not define a parameter, there is an implicit parameter called it, which is similar to the function of this. It stands for closure parameters. Example code for a closure with no arguments:

def noParamClosure = { -> true }
Copy the code

Note: Omit the parentheses

The last argument to the function is a closure, similar to the use of the callback function, as follows:

task JsonChao {
    doLast ({
        println "love is peace~"}})// It seems as if doLast will execute immediately
task JsonChao {
    doLast {
        println "love is peace~"}}Copy the code

The use of closures

There are four common uses for closures:

  • 1) Use in combination with basic types.
  • 2) in combination with the String class.
  • 3) Combination with data structure.
  • 4), combined with documents, etc.

The closure in order

  • 1) Key variables of closures
    • this
    • owner
    • delegate
  • 2) Closure delegate strategy

Key variables for closures

This and owner and delegate

The difference codes are as follows:

def scrpitClouser = {
    // represents the class at the closure definition
    printlin "scriptClouser this:" + this 
    // represents the class or object at the closure definition
    printlin "scriptClouser this:" + owner
    // Represents any object. Default is the same as ownner
    printlin "scriptClouser this:" + delegate 
}
    
// Outputs are scrpitClouse objects
scrpitClouser.call()

def nestClouser = {
    def innnerClouser = {
        // represents the class at the closure definition
        printlin "scriptClouser this:" + this 
        // represents the class or object at the closure definition
        printlin "scriptClouser this:" + owner
        // Represents any object, default with ownner always
        printlin "scriptClouser this:" + delegate 
    }
    innnerClouser.call()
}
    
// This outputs a nestClouser object, while owner and delegate outputs innnerClouser objects
nestClouser.call()
Copy the code

As you can see, if we define a closure directly within a class, method, or variable, the values of all three key variables are the same. However, if we nested a closure within the closure, the values of this, owner, and delegate are not the same. In other words, this will also point to the class or instance itself at our closure definition, and the Owner and delegate will point to the closure object closest to it.

Delegate vs. this and owner

The difference codes are as follows:

def nestClouser = {
    def innnerClouser = {
        // represents the class at the closure definition
        printlin "scriptClouser this:" + this 
        // represents the class or object at the closure definition
        printlin "scriptClouser this:" + owner
        // Represents any object. Default is the same as ownner
        printlin "scriptClouser this:" + delegate 
    }
    
    Change the default delegate
    innnerClouser.delegate = p 
    innnerClouser.call()
}

nestClouser.call()
Copy the code

As you can see, the delegate value can be changed, and the delegate value will be different from ownner’s value only if we change the delegate value.

Delegate strategy for closures

The sample code is shown below:

def stu = new Student()
def tea = new Teacher()
stu.pretty.delegate = tea
// In order for the pretty Closure's delegate changes to take effect, you must select its delegate policy as Closure.DELEGATE_ONLY, which defaults to Closure.OWNER_FIRST.
stu.pretty.resolveStrategy = Closure.DELEGATE_ONLY
println stu.toString()
Copy the code

Note that for the delegate changes to the pretty Closure described above to take effect, you must select its delegate policy as Closure.DELEGATE_ONLY, which is the default for Closure.OWNER_FIRST.

3. Groovy data structures

There are four commonly used data structures in Groovy:

  • 1) Array
  • 2), the List
  • 3), the Map
  • 4), the Range

The use of arrays is similar to the Java language, with perhaps the biggest difference being the extension of the definition, as shown in the following code:

// Array definition
def array = [1.2.3.4.5] as int[]
int[] array2 = [1.2.3.4.5]
Copy the code

Now, let’s look at three other data structures.

1, the List

The List is a linked List whose underlying interface corresponds to the List interface in Java. Generally, ArrayList is used as the real implementation class. The List variable is defined by [], and its elements can be any object.

Elements in a linked list can be accessed by index without fear of index crossing. If the index exceeds the current List length, the List automatically adds elements to the index. Let’s look at some of the most commonly used operations on List.

1) Sorting

def test = [100."hello".true]
// A left shift adds a new element to the List
test << 200
/ / the list definition
def list = [1.2.3.4.5]
/ / sorting
list.sort()
// Use your own sorting rulesSortlist.sort {a, b -> a == b?0 : 
            Math.abs(a) < Math.abs(b) ? 1 : - 1
} 
Copy the code

2) add

/ / add
list.add(6)
list.leftShift(7)
list << 8
Copy the code

3) Delete

/ / delete
list.remove(7)
list.removeAt(7)
list.removeElement(6)
list.removeAll { return it % 2= =0 }
Copy the code

4) Search

/ / to find
int result = findList.find { return it % 2= =0 }
def result2 = findList.findAll { return it % 2! =0 }
def result3 = findList.any { return it % 2! =0 }
def result4 = findList.every { return it % 2= =0 }
Copy the code

5) Obtain the minimum and maximum value

// Minimum value, maximum value
list.min()
list.max(return Math.abs(it))
Copy the code

6) Count the quantity that meets the conditions

// Count the number of conditions
def num = findList.count { return it >= 2 }
Copy the code

Map

Represents a key-value table, whose underlying counterpart is the LinkedHashMap in Java.

The Map variable is defined by [:], with key to the left and Value to the right of the colon. Key must be a string and value can be any object. In addition, the key can be wrapped in ‘or “, or without quotation marks. Let’s take a look at some of the most commonly used operations for Map.

1) Access

The sample code is shown below:

aMap.keyName
aMap['keyName']
aMap.anotherkey = "i am map"
aMap.anotherkey = [a: 1.b: 2]
Copy the code

2), each method

If the closure we pass is a parameter, it takes Entry as an argument. If we pass a closure with two arguments, it takes key and value as arguments.

def result = ""
[a:1.b:2].each { key, value -> 
    result += "$key$value" 
}
    
assert result == "a1b2"
    
def socre = ""
[a:1.b:2].each { entry -> 
    result += entry
}
    
assert result == "a=1b=2"
Copy the code

3) eachWithIndex method

If the closure takes two parameters, map.entry and the item’s index (a zero-based counter) are passed; Otherwise, if the closure takes three parameters, the key, value, and index are passed.

def result = ""
[a:1.b:3].eachWithIndex { key, value, index -> result += "$index($key$value)" }
assert result == "0(a1)1(b3)"

def result = ""
[a:1.b:3].eachWithIndex { entry, index -> result += "$index($entry)" }
assert result == "0(a=1)1(b=3)"
Copy the code

4) groupBy method

To group the closures according to their conditions, the code looks like this:

def group = students.groupBy { def student ->
    return student.value.score >= 60 ? 'pass' : 'Fail'
}
Copy the code

5) findAll method

It takes two arguments, and findAll passes in the Key and the Value. Also, if Closure returns true, the element is what you want, and if false, it is not what you are looking for.

Range

Range, which is actually an extension of List. It is represented by the begin value + two dots + end value. If you do not want to include the last element, the begin value + two dots + < + end is indicated. We can obtain the corresponding boundary elements by arange. from and arange. to.

If you need to learn more about how to manipulate data structures, you can refer directly to the Groovy API documentation.

4. Groovy is object-oriented

Groovy classes and their variables are public by default if you don’t declare public/private access.

1) Metaprogramming (Groovy runtime)

The Groovy runtime logic flow diagram looks like this:

To better illustrate the use of metaprogramming, we will first create a Person class and call its CRY method as follows:

// In the first Groovy file
def person = new Person(name: 'Qndroid'.age: 26)
println person.cry()

// In the second groovy file
class Person implements Serializable {

    String name

    Integer age

    def increaseAge(Integer years) {
        this.age += years
    }

     /** * if a method is not found, it is called instead of * @param name * @param args * @return */
     def invokeMethod(String name, Object args) {

        return "the method is ${name}, the params is ${args}"
    }


    def methodMissing(String name, Object args) {

        return "the method ${name} is missing"}}Copy the code

To implement metaprogramming, we need to use metaClass, as shown in the following example:

ExpandoMetaClass.enableGlobally()
// Add an attribute to the class dynamically
Person.metaClass.sex = 'male'
def person = new Person(name: 'Qndroid'.age: 26)
println person.sex
person.sex = 'female'
println "the new sex is:" + person.sex
// Dynamically add methods to classes
Person.metaClass.sexUpperCase = { -> sex.toUpperCase() }
def person2 = new Person(name: 'Qndroid'.age: 26)
println person2.sexUpperCase()
// Add static methods to the class dynamically
Person.metaClass.static.createPerson = {
    String name, int age -> new Person(name: name, age: age)
}
def person3 = Person.createPerson('renzhiqiang'.26)
println person3.name + " and " + person3.age
Copy the code

It is important to note that the method of adding an element through the metaClass of the class needs to be added again each time it is used. Fortunately, we can call globally valid handling before injection, as shown below:

ExpandoMetaClass.enableGlobally()
// We can add methods to third-party classes during application initialization
Person.metaClass.static.createPerson = { String name,
                                              int age ->
    new Person(name: name, age: age)
}
Copy the code

2) Variables and scopes in scripts

For each Groovy script, it generates a static void main function, which calls a run function, and all the code in the script is contained within the run function. You can use the groovyc command to copy the compiled class files to the Classes folder:

Groovyc is a groovy compile command, and -d classes is used to copy compiled class files into the classes folder
groovyc -d classes test.groovy
Copy the code

When we define a variable in a Groovy script, it is not accessible to other methods in the script or other scripts because it is actually created in the run function. At this point, we need to mark the current variable as a member variable using @field, which looks like this:

import groovy.transform.Field; 
    
@Field author = JsonChao
Copy the code

Iv. Document processing

1. Routine document processing

1) Read the file

EachLine method

We can use the eachLine method to read eachLine of the file and its only argument is a Closure that takes the contents of eachLine of the file. The sample code looks like this:

def file = newEachLine {String oneLine -> println oneLine}def text = file.getText()
def text2 = file.readLines()

file.eachLine { oneLine, lineNo ->
    println "${lineNo} ${oneLine}"
}
Copy the code

We can then use ‘targetfile.bytes’ to get the contents of the file directly.

Using InputStream

Alternatively, we can stream files, as shown in the following code:

// Open the ISM and close it
def ism = targetFile.newInputStream() 
// do sth
ism.close
Copy the code

Operate inputStream using closures

Using closures to operate on inputStream is more powerful, and is recommended as follows:

targetFile.withInputStream{ ism ->
    // Do not use close to operate the ISM. Groovy will automatically close for you
}
Copy the code

2) Write a document

About writing files there are two common forms of operation, namely through withOutputStream/withInputStream or withReader/withWriter writing. The sample code looks like this:

With withOutputStream/, withInputStream copy file

def srcFile = newFile(source File name)def targetFile = newThe File (the target File name) targetFile. WithOutputStream {OS - > srcFile. WithInputStream {ins - > OS < < insOutput from inputStream to OutputStream // using the << operator overload of OutputStream}}Copy the code

WithReader, withWriter copy file

def copy(String sourcePath, String destationPath) {
    try {
        // Create the target file first
        def desFile = new File(destationPath)
        if(! desFile.exists()) { desFile.createNewFile() }//开始copy
        new File(sourcePath).withReader { reader ->
            def lines = reader.readLines()
            desFile.withWriter { writer ->
                lines.each { line ->
                    writer.append(line + "\r\n")}}}return true
    } catch (Exception e) {
        e.printStackTrace()
    }
    return false
}
Copy the code

In addition, we also can be read by withObjectOutputStream/withObjectInputStream to preserve and Object. The sample code looks like this:

Save the corresponding Object to the file

def saveObject(Object object, String path) {
    try {
        // Create the target file first
        def desFile = new File(path)
        if(! desFile.exists()) { desFile.createNewFile() } desFile.withObjectOutputStream { out -> out.writeObject(object) }return true
    } catch (Exception e) {
    }
    return false
}
Copy the code

Read an Object from a file

def readObject(String path) {
    def obj = null
    try {
        def file = new File(path)
        if (file == null| |! file.exists())return null
        // Read objects from files
        file.withObjectInputStream { input ->
            obj = input.readObject()
        }
    } catch (Exception e) {

    }
    return obj
}
Copy the code

2. XML file operation

1) Get XML data

First, we define a string containing XML data, as follows:

final String xml = 
       
        
         
           
           
          
          
          
           </author> </book> <book available="13" ID ="3">   
           
            <author ID ="4">  
            
           
           
         
         
         
          
          Vue  
           
          
         
        
        
       '''
Copy the code

We can then use XmlSlurper to parse this XML data as follows:

def xmlSluper = new XmlSlurper()
def response = xmlSluper.parseText(xml)

// Get a specific attribute value by specifying a label
println response.value.books[0].book[0].title.text()
println response.value.books[0].book[0].author.text()
println response.value.books[1].book[0].@available

def list = []
response.value.books.each { books ->
    // Start traversing the book node
    books.book.each { book ->
        def author = book.author.text()
        if (author.equals('李刚')) {
            list.add(book.title.text())
        }
    }
}
println list.toListString()
Copy the code

2) Two traversal methods to obtain XML data

There are two traversal methods for retrieving XML data: deep traversal of XML data and wide traversal of XML data. Let’s take a look at their respective uses, as follows:

Deep traversal of XML data

def titles = response.depthFirst().findAll { book ->
    return book.author.text() == '李刚' ? true : false
}
println titles.toListString()
Copy the code

Breadth traverses XML data

def name = response.value.books.children().findAll { node ->
    node.name() == 'book' && node.@id= ='2'
}.collect { node ->
    return node.title.text()
}
Copy the code

In practice, we can use XmlSlurper to get the versionName of androidmanifest.xml as follows:

def androidManifest = new XmlSlurper().parse("AndroidManifest.xml") println androidManifest['@android:versionName']
或者
println androidManifest.@'android:versionName'
Copy the code

3) Generate XML data

In addition to parsing XML data with XmlSlurper, we can also use xmlBuilder to create XML files, as shown in the following code:


       
       
        Java
        
       
        Groovy
        
       
         JavaScript < language > < / langs > * /
       
      
def sw = new StringWriter()
// The core class used to generate XML data
def xmlBuilder = new MarkupBuilder(sw) 
// Langs was created successfully
xmlBuilder.langs(type: 'current'.count: '3'.mainstream: 'true') {
    // The first language node
    language(flavor: 'static'.version: '1.5') {
        age('16')
    }
    language(flavor: 'dynamic'.version: '1.6') {
        age('10')
    }
    language(flavor: 'dynamic'.version: '1.9'.'JavaScript')}// println sw

def langs = new Langs()
xmlBuilder.langs(type: langs.type, count: langs.count,
        mainstream: langs.mainstream) {
    // Walk through all the children
    langs.languages.each { lang ->
        language(flavor: lang.flavor,
                version: lang.version, lang.value)
    }
}

println sw
    
// corresponds to the LANGs node in XML
class Langs {
    String type = 'current'
    int count = 3
    boolean mainstream = true
    def languages = [
            new Language(flavor: 'static'.version: '1.5'.value: 'Java'),
            new Language(flavor: 'dynamic'.version: '1.3'.value: 'Groovy'),
            new Language(flavor: 'dynamic'.version: '1.6'.value: 'JavaScript')]}// corresponds to the LANGUang node in XML
class Language {
    String flavor
    String version
    String value
}
Copy the code

4) Json in Groovy

Instead of using Gson to parse network responses, we can use the JsonSlurper class provided in Groovy to avoid introducing the Gson library when we write the plug-in, as shown in the following example:

def reponse =
        getNetworkData(
                'http://yuexibo.top/yxbApp/course_detail.json')

println reponse.data.head.name
    
def getNetworkData(String url) {
    // Send an HTTP request
    def connection = new URL(url).openConnection()
    connection.setRequestMethod('GET')
    connection.connect()
    def response = connection.content.text
    // Convert json to entity objects
    def jsonSluper = new JsonSlurper()
    return jsonSluper.parseText(response)
}
Copy the code

Five, the summary

In this article, we learned the essential core syntax in Groovy from four aspects:

  • 1) Basic syntax of variables, strings, loops, etc.
  • 2) Data structures in Groovy: arrays, lists, maps, ranges.
  • 3) Groovy’s object-oriented, powerful runtime mechanism for methods, classes, etc.
  • 4) Processing of ordinary files, XML and JSON files in Groovy.

In the future, we will use these skills when we customize Gradle plug-ins. Therefore, it is important to have a good command of Groovy. Only with a solid foundation can we go further.

Reference links:

  • 1. Groovy API detail documentation

  • 2. Chapter 1-5 “MoOCs Gradle3.0 Automation Project Construction Technology Intensive + Actual Combat”

  • 3. Understanding Android Gradle in Depth

  • Gradle from the Beginning to the Practical – Groovy basics

  • 5. Groovy Script Basics Overview

Thank you for reading this article and I hope you can share it with your friends or technical group, it means a lot to me.

I hope we can be friends inGithub,The Denver nuggetsTo share knowledge.