本文主要包括:
|---Gradle簡介,下載,安裝
|---Groovy語言的簡單認識
|---Gradle構建java項目
|---Gradle構建腳本的書寫
|---Gradle構建java多模塊項目
|---Gradle在Android中的應用
|---最後寫一個建立文件夾的小插件
複製代碼
百分之八十的Gradle使用者應該都是從
AndroidStudio
接觸Gradle
的java
想當年用Eclipse喜歡收藏jar包,但版本迭代後,還要從新找
雖然挺麻煩,可是有jar包用感受也是無比幸福的,畢竟別人的心血能省本身很多事
畢竟簡單的學習小項目不須要那麼多第三方依賴,更不用說什麼依賴管理
當我剛用AndroidStudio時,最不解的就是Gradle,開始一段時間基我倆井水不犯河水
我依然用着個人jar包,在src下寫代碼,彷佛不用Gradle也沒什麼影響
第一次接觸Gradle是看一片介紹oKHttp的文章,照着寫一句,而後神奇的就OK了
這讓我很驚訝,當看到源碼時發現已經下載到本地了。心想:如今這麼智能了?
當我發現斷網狀況下依然可使用本地的庫文件,jar包就被我完全拋棄了
一直以來Gradle對我來講就是添加依賴,感受熟悉又陌生
就像一我的一直幫你幹活,你卻對它除了工做以外一無所知,這顯然不太好
複製代碼
Ant: 長江後浪推前浪,前浪已經over了
|---編譯、測試、打包
Maven:使用xml標記構建腳本
|---依賴管理、編譯、測試、打包、發佈
Gradle:使用Groovy語言構建腳本
|---依賴管理、編譯、測試、打包、發佈、靈活的腳本
複製代碼
一個基於
Groovy語言
的開源項目自動化構建工具
若是你用過AndroidStudio,Gradle已經被你下好了,直接打開下面的路徑
你能夠將bin目錄加入環境變量,下面的幾點就不用看了,android
C:\Users\Administrator>java -version
java version "10.0.1" 2018-04-17
Java(TM) SE Runtime Environment 18.3 (build 10.0.1+10)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.1+10, mixed mode)
複製代碼
將解壓後的bin文件夾目錄加到環境變量便可,ios
C:\Users\Administrator>gradle -v
Welcome to Gradle 5.2!
Here are the highlights of this release:
- Define sets of dependencies that work together with Java Platform plugin
- New C++ plugins with dependency management built-in
- New C++ project types for gradle init
- Service injection into plugins and project extensions
複製代碼
基於java虛擬機的動態語言
面向對象/腳本,徹底兼容java語法
複製代碼
注:目前2019-2-7日:
gradle-5.2
在Idea裏Build失敗,gradle-4.10.1
沒問題
估計是Idea插件的版本未更新,PS(Android目前也是用的gradle-4.10.1
)git
修改Gradle配置,出現下面的界面,Gradle插件就運行ok了github
---->[java]------------------
public class Version {
private int major;
private int minor;
public Version(int major, int minor) {
this.major = major;
this.minor = minor;
}
public int getMajor() {
return major;
}
public void setMajor(int major) {
this.major = major;
}
public int getMinor() {
return minor;
}
public void setMinor(int minor) {
this.minor = minor;
}
}
Version version = new Version(2, 1);
System.out.println(version.getMajor()); //2
---->[Groovy]------------------
class Version {
private int major
private int minor
Version(int major, int minor) {
this.major = major
this.minor = minor
}
}
def version = new Version(2, 1)
println version.major //2
複製代碼
類及方法默認public,字段自動getter,setter,直接點號獲取
最後一個表達式的值做爲返回值
== 等用於equals(),assert語句,弱類型,
分號可選,擴號可選,字符串三種,閉包
複製代碼
def age = 24//推到類型
assert age < 25 //斷言
println age//省略括號
def name = '張風捷特烈'//單引號字符串
def say = "我是${name}"//雙引號插值字符串
def code = //三引號原樣輸出
''' 我是${name} def age = 24//推到類型 assert age < 25 //斷言 '''
println say
println code
//list
def platform = ["java", "Android", "ios"]//定義集合
platform << 'Linux'//添加元素
println platform.class//class java.util.ArrayList
println platform.size()//4
//map
def release = [
'v0.01': '2018-12-13',
'v0.02': '2018-12-14',
'v0.03': '2018-12-15']
release.'v0.04' = '2018-12-16'//添加
println release.getClass()//class java.util.LinkedHashMap
println release.size()//4
//閉包
def update ={
v-> return v+1
}
def updateFun(Closure closure,int version) {
closure(version)
}
def newVersion = updateFun(update, 1)
println newVersion//2
複製代碼
Idea會爲咱們自動生成項目結構編程
/**
* 做者:張風捷特烈
* 時間:2019/2/7/007:8:58
* 郵箱:1981462002@qq.com
* 說明:將字符大寫方法
*/
public class UpCase {
public static String toUpCase(String str) {
System.out.println(str);
return str.toUpperCase();
}
}
複製代碼
打jar包很是簡單,點兩下就好了,(其中字符集的問題
後面解決
,不影響jar包使用)api
打了jar包就用用吧,雖然實際中已經不多用jar包依賴了,這裏演示一下
新建一個App的module,將jar包導入,並依賴,而後就能正常使用了緩存
在
gradle根目錄\src\core-api\org\gradle\api\Project.java
是一個interface
它定義了一個項目類,而build.gradle
中即便用了項目對象的屬性和方法
這兩個類是Gradle的核心,其中定義了不少方法,能夠在.gradle文件中隨意調用bash
|---好比打印一下當前項目目錄
---->[org.gradle.api.Project#getProjectDir]-------
/**
* <p>The directory containing the project build file.</p>
*
* @return The project directory. Never returns null.
*/
File getProjectDir();
---->[App/build.gradle]----------
println getProjectDir()//J:\Java\GradleTest\toly\App
複製代碼
task
public interface Task extends Comparable<Task>, ExtensionAware
Task是一個接口,能夠助你完成一些無聊的工做,這裏以建立三個文件夾爲例微信
def mkDir = {//建立文件夾的方法
path ->
def dir = new File(path)
if (!dir.exists()) {
dir.mkdirs()
}
}
task mkDirTask() {//自定義一個任務
def paths = [
'src/main/java/com/toly1994/app/adapter',
'src/main/java/com/toly1994/app/activity',
'src/main/java/com/toly1994/app/fragment',
]
doFirst {
paths.forEach(mkDir)
}
}
複製代碼
若是上面的看懂了,這裏用projectName替換一下項目名
這樣就能夠在任意項目裏建立這三個文件夾了,
task mkDirTask() {//自定義一個任務
def projectName = project.name.toLowerCase()//獲取工程目錄
def paths = [
"src/main/java/com/toly1994/${projectName}/adapter",
"src/main/java/com/toly1994/${projectName}/activity",
"src/main/java/com/toly1994/${projectName}/fragment",
]
doFirst {
paths.forEach(mkDir)
}
}
複製代碼
dependsOn
也就是在執行以前,先執行被依賴的Task
task mkDirTaskWithUtils{
dependsOn 'mkDirTask'//依賴mkDirTask任務
def projectName = project.name.toLowerCase()//獲取去工程目錄
def paths = [
"src/main/java/com/toly1994/${projectName}/utils"
]
doFirst {
paths.forEach(mkDir)
}
}
複製代碼
//在構建項目前調用的鉤子函數
gradle.beforeProject {
project ->
println "-------beforeProject-------"
}
//配置解析前回調
gradle.taskGraph.whenReady {
graph ->
println "-------whenReady-------"
}
gradle.buildFinished {
result ->
println "-------buildFinished-------"
}
複製代碼
關於implementation和compile的區別,這裏簡單說一下。可詳見:
工件座標:(group,name,version)
工件倉庫:mavenCentral/jcenter
依賴的傳遞:若A-->B B-->C 則A-->C
implementation(編譯期)-----曾經爲compile
|--1.加快編譯速度(本模塊編譯)。
|--2.對外隱藏沒必要要的接口。
runtime(運行期)、testCompile(測試編譯期)、testRuntime(測試運行期)
複製代碼
//使用mavenCentral倉庫
repositories {
mavenCentral()
}
//依賴管理
dependencies {
//測試編譯時依賴
testCompile group: 'junit', name: 'junit', version: '4.12'
複製代碼
maven倉庫相比你們都知道吧,簡單說一下怎麼查看一個依賴(okhttp爲例):倉庫網址
能夠看到okhttp的工件座標(group,name,version),它肯定了惟一的存在
//依賴管理
dependencies {
//測試編譯時依賴
testCompile group: 'junit', name: 'junit', version: '4.12'
// https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp
implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.13.1'
}
複製代碼
//簡寫形式 implementation'組:名:版本號' -----是否是很親切
implementation 'com.squareup.okhttp3:okhttp:3.13.1'
複製代碼
/**
* 做者:張風捷特烈
* 時間:2019/2/8/008:10:27
* 郵箱:1981462002@qq.com
* 說明:測試使用okhttp
*/
public class Api {
public static void main(String[] args) {
doGet("http://www.toly1994.com:8089/api/android/note");
}
public static void doGet(String url) {
//1.獲取OkHttpClient對象
OkHttpClient okHttpClient = new OkHttpClient();
//2.獲取Request對象
Request request = new Request.Builder().get().url(url).build();
//3.將Request封裝爲Call對象
Call call = okHttpClient.newCall(request);
//4.執行Call
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
System.out.println(e);
}
@Override
public void onResponse(Call call, Response response) throws IOException
String str = response.body().string();
System.out.println(str);
}
});
}
}
複製代碼
前面找不到就找下一個
repositories {
mavenCentral()//使用mavenCentral倉庫
google()//使用google倉庫
jcenter()//使用jcenter倉庫
maven {//maven私服
url 'https://jitpack.io'
}
}
複製代碼
okhttp:3.13.1
依賴了okio:1.17.2
,若是項目中再依賴okio:2.2.2
就會版本衝突
默認狀況下版本衝突時,Gradle會自動使用最高版本,因此咱們並不怎麼煩神
自動使用最高版本,大多數狀況都適用,但你仍是有自定義解決方案的機會的
首先,顯示版本衝突在哪裏
configurations.all{
resolutionStrategy{
failOnVersionConflict()//版本衝突時報錯
}
}
複製代碼
configurations.all {
resolutionStrategy {
// failOnVersionConflict()//版本衝突時報錯
force 'com.squareup.okio:okio:1.17.2'//強制指定版本
}
}
複製代碼
implementation('com.squareup.okhttp3:okhttp:3.13.1'){
exclude group: 'com.squareup.okio',module:'okio'
}
複製代碼
一個項目只有一個,用來管理子模塊名稱
rootProject.name = 'toly-all'
include 'model'
include 'repository'
include 'player'
複製代碼
implementation project(":模塊名")
-或compile
注意:項目間的傳遞型依賴要用compile,否則引用不到
---->[toly-all\repository\build.gradle]------------
dependencies {
compile project(":model")
testCompile group: 'junit', name: 'junit', version: '4.12'
}
---->[toly-all\player\build.gradle]------------
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile project(":repository")
}
---->[toly-all\build.gradle]------------
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
implementation project(":player")
}
複製代碼
每一個
build.gradle
都有的東西,統一處理一下,之後改起來方便 在根項目下的build.gradle
裏使用allprojects
---->[toly-all\build.gradle]------------
allprojects {
apply plugin:'java'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
}
}
複製代碼
gradle.properties
統一配置參數---->[toly-all\gradle.properties]------------
group='com.toly1994'
version='0.01'
複製代碼
public class PlayerTest {
@Test
public void tolySay() {
Player player = new Player();
Person person = player.tolySay();
assert person.name.equals("toly");
assert person.age == 24;
}
}
複製代碼
使用maven-publish插件,發表到中央倉庫挺麻煩的,仍是本身搭個私服,或直接本地吧
以上是Gradle在java中的使用,如今回頭看一下Android裏的Gradle,你應該更有感受
---->[模塊:build.gradle]-----------------
apply plugin: 'com.android.application' //啓用插件 com.android.application
android {//安卓
compileSdkVersion 27//SDK編譯版本
defaultConfig {//默認配置
applicationId "com.toly1994.gradletest"//應用id
minSdkVersion 21//兼容的SDK最低版本
targetSdkVersion 27//SDK目標版本(本應用的SDK--向下兼容)
versionCode 1//版本號
versionName "1.0" //版本名稱
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {//build配置
release {//發佈設置
minifyEnabled false //是否混淆
//混淆文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {//依賴
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
---->[項目:build.gradle]-----------------
buildscript {//構建腳本
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {//對全部模塊適用
repositories {//倉庫
google()//google倉庫
jcenter()//jcenter倉庫
}
}
task clean(type: Delete) {//清除的task
delete rootProject.buildDir
}
複製代碼
模塊級的gradle文件多了
externalNativeBuild
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
...
externalNativeBuild {//設置cmake的目錄
cmake {
path "CMakeLists.txt"
}
}
}
複製代碼
將
stringFromJNI
抽取出來放在一個類中做爲靜態方法,而後生成so文件
注意so文件在其餘工程下須要保證接口名的一致,比不剛纔的C++中的函數:
Java_com_toly1994_jni_HelloJNI_stringFromJNI
該函數只能用在:com.toly1994.jni下的HelloJNI類中的stringFromJNI方法,錯一個字都不行
android {//安卓
...
sourceSets {//------默認以下,可不用配置
main {
jni.srcDirs = []
jniLibs.srcDirs = ['src/main/jniLibs']//默認路徑,可修改
}
}
}
複製代碼
這裏以佈局爲例,其餘資源文件夾也同樣
android {
...
sourceSets {
main {
res.srcDirs = [
'src/main/res/layouts/home',
'src/main/res/layouts/player',
'src/main/res/layouts/news',
'src/main/res'
]
}}
}
複製代碼
public interface AndroidSourceSet
接口定義不少文件的位置
均可以根據本身的須要,自行修改
res.srcDirs 資源文件目錄
assets.srcDirs assets文件目錄
aidl.srcDirs aidl文件目錄
jniLibs.srcDirs .so文件目錄
jni.srcDirs jni文件目錄
manifest.srcFile AndroidManifest.xml的位置
java.srcDirs java代碼的文件目錄
複製代碼
提一下:
gradle.properties
裏的鍵值對能夠在.gradle裏直接使用
你能夠將密碼寫在裏面,.gitignore
配置一下,不上傳到github就好了
android {
...
signingConfigs {
release {
storeFile file("tolyapp.jks")
storePassword APK_SIGN_STORE_PASSWORD
keyAlias "toly"
keyPassword APK_SIGN_KEY_PASSWORD
}
}
buildTypes {
release {
shrinkResources true//是否去除未利用的資源,默認false,表示不去除。
minifyEnabled true//是否混淆
signingConfig signingConfigs.release//簽名
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
---->[gradle.properties]--------------
APK_SIGN_KEY_PASSWORD=777777
APK_SIGN_STORE_PASSWORD=666666
複製代碼
ext
對於不少公共的東西,提取出來容易統一管理和修改,特別對於多模塊項目而言
.gradle 文件一直被我認爲是神聖的存在,不能亂改,更別提本身建立了
騎士gradle文件是能夠相互引用的,下面經過建立文件夾小插件來講明
---->[mkdir.gradle]---------
import java.util.function.Consumer
apply plugin: 'com.android.application'
apply plugin: MkDirPlugin//聲明使用插件
mkDir {//根據拓展參數來自定義文件夾
pkg = 'com.toly1994.gradletest_'
names = ['adapter','activity','app/config',
'app/compat','utils','view','presenter','model']
}
//----------------------------如下是插件部分--------------------------------
class MkDirPlugin implements Plugin<Project> {
//該接口定義了一個apply()方法,在該方法中,咱們能夠操做Project,
//好比向其中加入Task,定義額外的Property等。
void apply(Project project) {
//加載Extension
project.extensions.create("mkDir", MkDirPluginPluginExtension)
def mkDir = {
//建立文件夾的方法
path ->
def dir = new File(path)
if (!dir.exists()) {
dir.mkdirs()
}
}
//使用Extension配置信息
project.task('mkDirTask') << {
String pkg = project.mkDir.pkg
ArrayList<String> names = project.mkDir.names
def dir='src/main/java/'+pkg.replaceAll("\\.",'''/''')
ArrayList<String> paths = new ArrayList<>()
names.forEach(new Consumer<String>() {
@Override
void accept(String s) {
paths.add(dir+"/"+s)
println dir+"/"+s
}
})
paths.forEach(mkDir)
}
}
}
class MkDirPluginPluginExtension {//拓展參數
String pkg = ''
def names = []
}
//----------------------------插件結束--------------------------------
---->[模塊級build.gradle]--------------
apply from: 'mkdir.gradle' //引用mkdir.gradle ---一行搞定
複製代碼
插件部分你不用Groovy,所有用java寫均可以,Groovy對java是兼容的
插件你也能夠新建一個項目來製做
,能夠發佈一下,給更多人使用 因此燃燒你的小宇宙,用gradle盡情偷懶吧!相信你會發現另外一片天地!
項目源碼 | 日期 | 附錄 |
---|---|---|
V0.1-- | 2018-2-12 | 無 |
發佈名:
一代版本一代神[-Gradle-]
捷文連接:www.jianshu.com/p/075f84620…
筆名 | 微信 | |
---|---|---|
張風捷特烈 | 1981462002 | zdl1994328 |
個人github:github.com/toly1994328
個人簡書:www.jianshu.com/u/e4e52c116…
個人掘金:juejin.im/user/5b42c0…
我的網站:www.toly1994.com
1----本文由張風捷特烈原創,轉載請註明
2----歡迎廣大編程愛好者共同交流
3----我的能力有限,若有不正之處歡迎你們批評指證,一定虛心改正
4----看到這裏,我在此感謝你的喜歡與支持