понедельник, 18 апреля 2016 г.

Gradle. Работа с файловой системой.

Для работы с файловой системой мы используем типизированные задачи:
Бывают:
- copy
- zip
- delete


task copyJpegs(type: Copy) {
   from images
   include '*.jpg'
   into 'build'
}

task copyImageFoders(type: Copy) {
   from('images') {
      include '*.jpg'
      into 'jpeg'
   }
   from('images') {
      iclude '*.gif'
      into 'gif'
   }

   into 'build'
}

task zipImages(type: Zip) {
   baseName = 'images'
   destinationDir = file('build')
   from 'images'
}

task zipImageFolders(type: Zip) {
    baseName = 'images'
    destinationDir = file('build')

    from('images') {
        include '*.jpg'
        into 'jpeg'
    }

    from('images') {
        include '*.gif'
        into 'gif'
    }
}

task deleteBuild(type: Delete) {
    delete 'build'
}

task unpackBundle(type: Copy) {
    from zipTree('build/web.zip')
    into 'build/exploded'
}

Зависимости тасков Gradle

dependsOn - запускается сначала указанный/ые здесь
finalizedBy - запускается после таска указанный здесь
mustRunAfter - выстраивает порядок тасков: сначала указанный, потом текущий, вне зависимости от порядка указанного при запуске
shouldRunAfter - это менее строгий вариант предыдущего, порядок желательный, но есть два варианта, когда он нарушается: 1) когда используется правило, в котором предствлено упорядоченный цикл; 2) когда запускаются таски в паралельном режиме

myTask.onlyIf(new Spec() {
   boolean isSatisfiedBy(Task task) {
      return task.dependsOnTaskDidWork();
   }
});

четверг, 14 апреля 2016 г.

Основы Gradle

Ядро Gradle - это язык для программирования основанном на зависимостях: мы можем определять задачи и зависимости между ними.

Любой build.gradle скрипт делегирует свое тело в обьект project.
То есть
task myTask1 << {}
По сути:
project.task("myTask1", { doLast {}})
А теперь плавный переход от последнего к первому, чтобы было понятно, как такое может быть. Шаг1
task("myTask1", { doLast {}})
Шаг2
task "myTask1" { doLast {}} 
Шаг3
task myTask1  << doLast {}
Все по правилам груви + понимание того, что скрипт всегда выполняется в контексте глобального обьекта project.

Кроме того, project умеет искать среди своих тасков, если идет обращение не к его предопределенным полям/методам. Из-за этого мы можем обращаться к таске так:
myTask.description="My description"
myTask.group="Some group"
myTask.doLast({println "Do it last"}) 
myTask.doFirst {println "Do it first"}
myTask.leftShift {println "Do this even more last"} //leftShift is a method in groovy Object which provides possibility to execute provided closure when applying operator << for instance of the class. Этот метод таски считается алиасом doLast.
myTask << {println "Do this last of all"} //leftShift can be also defined by opertor << 
Методы do* не перегружают предыдущие замыкания, а добавляют в очередь, которая выполняется по порядку.

У обьекта project есть поле tasks, которое является списком, внутри которого все таски проекта.

Наиболее распространенный шаблон для создание простой таски, это создание и немедленная передача замыкания через оператор << в список действий doLast фазы;

task myTask2 << {
   println "Do it last"
}

Как можно было уже заметить, настраивать таску можно не через вызовы методов, а через замыкание настроек
task("myTask3", {
 description "Some"//this calls setter setDescription("Some")
 group="Some group"//this also callss setter, but we need always use = for collections
 doLast({println "Do it last"}) 
 doFirst {println "Do it first"}
 leftShift {println "Do this even more last"}
})
Или же все по сахарному, как и должно это писаться:
task myTask3 {
 description "Some"
 group "Some group"
 doLast {println "Do it last"}  
 doFirst {println "Do it first"}
 leftShift {println "Do this even more last"}
}

Некоторые свойста мы можем установить через декларацию таски, но так мы можем установить не все
task myTask3(description: "Some") << {println "Do it last"}
Единственное где мы обязанны пользоваться, только такой установкой свойства, это типизированная таска.

Когда срабатывают static в java


class A {
    private static int v = func();
    private static int func() {
        System.out.print("A");
        return 0;
    }
}

class B {
    private static int v = func();
    public static int func() {
        System.out.print("B");
        return 0;
    }
}

class C {
    private static int v = func();
    public static int func() {
        System.out.print("C");
        return 0;
    }
}

class Question {
    public static void main(String[] args) {
        B b;
        C.func();
        b = new B();
        System.out.println();
    }
}

Вывод будет: CCB

Почему так? Из спецификации:
Класс Т инициализируется в одном из следующий 5 случаев:
1. Создается объект класса Т.
2. Вызывется статичный метод класса Т.
3. Статичной переменной класса Т присваивается значение (вне класса).
4. Статичная (не константная) переменная класса Т используется.
5. Т - внешний класс и внутри него выполняется конструкция assert.

Таким образом первое упоминание класса В не запускает инициализацию класса.

пример взят из http://www.quizful.net/