让gradle task可以执行多次

在开发中遇到这个需求,google也没能找到答案,最后自己解决了,分享出来给大家参考参考。

默认情况下gradle的task都是只能执行一次的,如下面的代码

task a {  
    println("execute function a !!!!!!!!!!!!!!!!!!"); 
} 
a.execute()  
a.execute()  
a.execute()  

运行后发现task a仅仅执行了一次,为啥只执行一次呢,开始分析通过查看 AbstractTask::execute()方法如下

public final void execute() {  
    this.getExecuter().execute(this, this.state, new DefaultTaskExecutionContext());
    this.state.rethrowFailure(); 
}

通过观察发现是the.state的问题,state的类型是TaskStateInternal,里面记录了task当前的状态,executing正在执行,executed执行完成等等

知道这个状态影响了task多次执行,但是我们还是没有解决我们的问题,再来看看TaskExecuter类,TaskExecuter是一个接口,定义了executing()方法

public interface TaskExecuter {  
    void execute(TaskInternal var1, TaskStateInternal var2, TaskExecutionContext var3); 
}

再来看看TaskExecuter的实现类有哪些?

ExecuteAtMostOnceTaskExecuter引起了我的注意,让task最多执行一次的执行器,看看源码

public class ExecuteAtMostOnceTaskExecuter implements TaskExecuter {  
private static final Logger LOGGER = Logging.getLogger(ExecuteAtMostOnceTaskExecuter.class);  
private final TaskExecuter executer;  
public ExecuteAtMostOnceTaskExecuter(TaskExecuter executer) {  
    this.executer = executer; 
} 
public void execute(TaskInternal task, TaskStateInternal state, TaskExecutionContext context) {  
if(!state.getExecuted()) {  
    LOGGER.debug("Starting to execute {}", task);
 try { this.executer.execute(task, state, context); 
} finally {
 state.executed(); LOGGER.debug("Finished executing {}", task); 
} 
} 
} 
}

不出所料,就是根据state来判断不让多次执行。

那我们再来验证下,默认创建的task执行器到底是不死ExecuteAtMostOnceTaskExecuter呢?打印出来看看呗

task a { println("execute function a !!!!!!!!!!!!!!!!!!"); } a.execute() println(a.getExecuter()) a.execute() a.execute() // 执行结果 execute function a !!!!!!!!!!!!!!!!!! org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter@26aba89b

一切真相大白了,task不能多次执行的原因就是默认执行器是ExecuteAtMostOnceTaskExecuter,解决的方案自然也清晰了,用其他的执行器呗,我看ExecuteActionsTaskExecuter就蛮好的,我的解决方法如下

如果是自定义Task(继承DefaultTask)

重写getExecuter()方法即可

@Override TaskExecuter getExecuter() { return new ExecuteActionsTaskExecuter(new TaskActionListener() { @Override void beforeActions(Task task) { } @Override void afterActions(Task task) { } }); }

一般情况下给task设置setExecuter就好了

a.setExecuter(new ExecuteActionsTaskExecuter(new TaskActionListener() { @Override void beforeActions(Task task) { } @Override void afterActions(Task task) { } }))